如何替换setTimeout或使用其替代方案?能否用requestAnimationFrame替代setTimeout实现延迟移除类以解决动画卡顿问题?
使用requestAnimationFrame替代setTimeout优化动画流畅度
当然可以用requestAnimationFrame替代这段setTimeout代码,而且这确实是更优的选择!setTimeout是基于固定延迟触发回调,但它不会和浏览器的刷新节奏同步——浏览器通常以60Hz(约16.6ms/帧)的频率重绘,如果setTimeout的回调时机刚好卡在两次重绘之间,就容易出现卡顿丢帧的情况。而requestAnimationFrame是浏览器专门为动画场景设计的API,它会自动对齐浏览器的重绘周期,确保你的操作在最合适的时机执行,从根源上减少动画卡顿。
转换后的代码实现
要实现“2秒后移除类”的需求,我们需要用requestAnimationFrame来逐帧检查时间差,当累计时间达到2000ms时执行移除操作:
function removeAnimationClassesAfterDelay(delay = 2000) { // 记录开始时间,用performance.now()获取高精度时间戳 const startTime = performance.now(); function checkElapsedTime() { const elapsed = performance.now() - startTime; if (elapsed >= delay) { // 获取目标元素,避免重复DOM查询 const prevSlide = customSlider.Components.Elements.slides[prevIndex]; const slideImg = prevSlide.querySelector('.rh02-img'); // 执行移除类的操作 removeClass(slideImg, 'fadeOutLeftImg'); removeClass(slideImg, 'fadeOutRightImg'); removeClass(prevSlide.querySelector('.rh08w5'), 'fadeOutText'); } else { // 未到延迟时间,继续请求下一帧检查 requestAnimationFrame(checkElapsedTime); } } // 启动帧循环 requestAnimationFrame(checkElapsedTime); } // 调用函数,触发2秒后的类移除操作 removeAnimationClassesAfterDelay();
额外优化小技巧
如果需要在某些场景下取消这个延迟操作,可以保存requestAnimationFrame的返回ID,用cancelAnimationFrame终止循环:
let rafCancelId; function removeAnimationClassesAfterDelay(delay = 2000) { const startTime = performance.now(); function checkElapsedTime() { const elapsed = performance.now() - startTime; if (elapsed >= delay) { // 执行移除类操作... } else { rafCancelId = requestAnimationFrame(checkElapsedTime); } } rafCancelId = requestAnimationFrame(checkElapsedTime); } // 若需取消操作,调用以下代码 // cancelAnimationFrame(rafCancelId);
这样实现既保证了2秒延迟的准确性,又能让你的动画和浏览器刷新节奏同步,彻底解决setTimeout带来的卡顿问题。
内容的提问来源于stack exchange,提问作者user944513
相关产品推荐
相关产品推荐

