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
相关产品推荐
相关产品推荐

