You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TypeScript实现div随机定位及循环淡入淡出效果问题求解

核心修改逻辑

  • 给每个定时器的触发逻辑拆分出淡出、等待动画结束、更新位置、淡入四个步骤,用setTimeout匹配CSS淡入淡出过渡时长实现时序控制
  • 给useEffect添加空依赖数组,避免组件重渲染时重复注册定时器
  • 新增定时器清理逻辑,组件卸载时清空所有定时器避免内存泄漏
export default function RandomVideos(){
  // 这里填你CSS中fade-in/fade-out的过渡时长,单位ms,示例用500ms
  const ANIMATION_DURATION = 500;

  useEffect(() => {
    const videos = Array.from(document.getElementsByClassName('video_container') as HTMLCollectionOf<HTMLElement>);
    const container = document.getElementById('container') as HTMLElement;
    const Width = container.offsetWidth;
    const Height = container.offsetHeight;
    // 存储所有定时器ID,用于卸载时清理
    const timerIds: number[] = [];

    function fadeIn(thisVideo: HTMLElement){
      thisVideo.classList.add('fade-in');
      thisVideo.classList.remove('fade-out');
    }

    function fadeOut(thisVideo: HTMLElement){
      thisVideo.classList.add('fade-out');
      thisVideo.classList.remove('fade-in');
    }

    function randomlyPlaced(){
      videos.forEach(thisVideo =>  {
        // 首次加载先随机位置直接淡入
        const randomTop = Math.round(Math.random() * Height) - 20;
        const randomLeft = Math.round(Math.random() * Width) - 20;
        thisVideo.style.top = randomTop +"px";
        thisVideo.style.left = randomLeft +"px";
        fadeIn(thisVideo);

        // 注册循环定时器,2-9秒随机触发和原逻辑保持一致
        const intervalId = setInterval(function() {
          // 第一步:先触发淡出
          fadeOut(thisVideo);
          // 等待淡出动画结束后,更新位置再触发淡入
          setTimeout(() => {
            const newRandomTop = Math.round(Math.random() * Height) - 20;
            const newRandomLeft = Math.round(Math.random() * Width) - 20;
            thisVideo.style.top = newRandomTop +"px";
            thisVideo.style.left = newRandomLeft +"px";
            fadeIn(thisVideo);
          }, ANIMATION_DURATION)
        }, (Math.floor(Math.random() * 7000) + 2000))
        timerIds.push(intervalId);
      })
    }

    randomlyPlaced()

    // 组件卸载时清理所有定时器
    return () => {
      timerIds.forEach(id => clearInterval(id));
    }
  }, []); // 空依赖,仅组件挂载时执行一次

  return(
    <div className="container" id="container">
        {RandomVideosProps.map((video) => (
            <div className="video_container" key={video.id}>
                <video src={video.src}></video>
                {video.text}
            </div>
        ))}
    </div>
  );
}

注意事项

  • 请先调整代码顶部的ANIMATION_DURATION值,和你CSS中.fade-in/.fade-out的transition过渡时长保持一致,避免动画还没结束就切换位置
  • 如果需要更精准的时序控制,避免硬编码时长,可以给video_container元素绑定transitionend事件监听,动画结束后自动触发位置更新,注意每次绑定后要对应解绑避免重复触发

内容的提问来源于stack exchange,提问作者wewiowe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:06:03