requestAnimationFrame数字滚动器核心是时间驱动线性插值,结合缓动函数、视口触发和逐位动画:用performance.now()计时,Math.min(elapsed/duration,1)控进度,Math.round()取整;加easeInOutQuad实现慢进快中慢出;IntersectionObserver在10%可见时启动并防重复;支持data-target读值及动态插入;多数字位可独立滚动并补零。

用 requestAnimationFrame 做数字滚动器,核心是让数值随时间平滑插值,而不是“每帧加1”。它绑定浏览器刷新节奏,不卡顿、不失帧、页面切后台自动暂停,比 setTimeout 或 setInterval 可靠得多。
基础动画函数:时间驱动 + 线性插值
从起始值到目标值,按真实经过时间计算当前应显示的数字,全程用浮点运算,最后四舍五入:
- 用
performance.now()记录开始时间,避免系统时间跳变干扰 - 每帧算出已过时间占比(
progress = Math.min(elapsed / duration, 1)),防止超调 - 当前值 =
start + (end - start) * progress,再用Math.round()显示整数 - 只在
progress < 1时继续调用requestAnimationFrame
加缓动效果:让滚动更自然
线性过渡太机械,换成缓动函数(如 easeInOutQuad)能模拟惯性感:
- 定义缓动函数:
t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t - 把原始
progress传进去,得到非线性的eased值 - 再代入插值公式:
current = start + (end - start) * eased - 视觉上就是“慢进→快中→慢出”,比匀速更符合直觉
视口触发:数字进入屏幕才开始动
页面一加载就跑动画,用户可能根本没看到。用 IntersectionObserver 控制时机:
立即学习“前端免费学习笔记(深入)”;
- 设置
threshold: 0.1,元素 10% 高度可见即触发 - 触发后立即执行动画,并调用
observer.unobserve(el)防止重复启动 - 支持动态插入的数字(如 AJAX 渲染后):插入 DOM 后手动调用
observer.observe(el) - HTML 中用
data-target="12345"存目标值,JS 读取并转为数字类型
多数字位独立控制(可选进阶)
如果要模拟“每位数字像滚轮一样滚动”的效果,需拆解数字逐位动画:
- 把目标数字转成字符串,按位拆成数组:
[1, 2, 3, 4, 5] - 为每位创建独立的
requestAnimationFrame循环,起始值统一设为 0 - 每位容器高度固定,内部用
transform: translateY(-数字×行高)定位(CSS 方案)或直接替换文本(JS 方案) - 注意补零逻辑:比如从 99 到 100,百位要从 0 滚到 1,不能漏掉



















