如何计算Javascript平滑滚动结束时长以触发后续动画?
检测平滑滚动结束并触发动画的方案
不需要刻意计算平滑滚动的时长——因为Chrome等浏览器的平滑滚动速度会根据滚动距离、设备性能甚至用户设置动态调整,直接检测滚动停止的状态才是更可靠的方案。以下是两种实用的实现方式:
方法一:Scroll事件 + 定时器防抖
利用平滑滚动过程中浏览器会持续触发scroll事件的特性,通过定时器“防抖”:每次滚动时重置定时器,当定时器到期且没有新的滚动事件触发,就判定滚动已停止。
let scrollEndTimer; // 监听全局滚动事件 window.addEventListener('scroll', () => { // 清除之前的定时器,重置计时 clearTimeout(scrollEndTimer); // 设置100ms延迟(可根据实际测试调整,80-150ms都适配Chrome) scrollEndTimer = setTimeout(() => { // 滚动停止后执行你的动画 runTargetAnimation(); }, 100); }); // 示例动画函数 function runTargetAnimation() { console.log('滚动已停止,开始执行动画'); // 这里写你的动画逻辑,比如元素淡入、位移等 }
方法二:RequestAnimationFrame 跟踪滚动位置
通过requestAnimationFrame同步浏览器渲染帧,对比连续几帧的滚动位置,若位置不变则判定滚动停止,精度比定时器更高。
let lastScrollPos = window.scrollY; let stationaryFrameCount = 0; let animationFrameId; function checkScrollStop() { const currentScrollPos = window.scrollY; if (currentScrollPos === lastScrollPos) { stationaryFrameCount++; // 连续3帧位置不变(约50ms,对应60fps),判定滚动停止 if (stationaryFrameCount >= 3) { runTargetAnimation(); // 停止检测 cancelAnimationFrame(animationFrameId); return; } } else { stationaryFrameCount = 0; lastScrollPos = currentScrollPos; } animationFrameId = requestAnimationFrame(checkScrollStop); } // 触发平滑滚动后启动检测(比如点击锚点后调用) // checkScrollStop(); function runTargetAnimation() { console.log('滚动已停止,开始执行动画'); // 你的动画逻辑 }
关键说明
- 无需纠结滚动速度计算:浏览器的平滑滚动算法是黑盒,不同场景下速度差异极大,直接检测停止状态比预估时长更稳定。
- 延迟参数可调整:第一种方法的100ms延迟可根据测试微调,确保在Chrome各种滚动场景下都能准确触发。
内容的提问来源于stack exchange,提问作者Jamzy01
相关产品推荐
相关产品推荐

