requestanimationframe实现动画的核心是按浏览器刷新节奏调度重绘,自动适配刷新率、失焦暂停、省电顺滑;需递归调用形成帧链,结合时间戳计算deltatime实现匀速,相比定时器具备自动节流、精准对齐重绘、更优底层调度等优势。

用 window.requestAnimationFrame() 实现动画,核心是让浏览器按自身刷新节奏(通常是每秒60帧)来调度重绘,而不是靠 setTimeout 或 setInterval “硬塞”时间间隔。它自动适配屏幕刷新率、页面失焦时暂停、更省电,动画自然就更顺滑。
requestAnimationFrame 的基本用法
它接收一个回调函数,该函数会在浏览器下一次重绘前执行。和定时器不同,它不接受毫秒参数,而是由浏览器决定最佳时机:
- 调用后不会立即执行,而是排队等待下一帧
- 返回一个整数ID,可用
cancelAnimationFrame(id)主动取消 - 回调函数默认传入一个
timestamp(DOMHighResTimeStamp),表示当前帧开始的时间戳(毫秒级,精度高)
手动实现循环动画的正确写法
不能只调用一次,需要在回调里递归调用自己,形成“一帧接一帧”的链式调度:
function animate() {
// 更新动画状态:比如修改元素 left/top/transform 等
element.style.transform = `translateX(${x}px)`;
x += 2;
<p>// 请求下一帧
requestAnimationFrame(animate);
}
requestAnimationFrame(animate); // 启动</p>
注意:不要用 setInterval(animate, 16) 模拟,那只是“假装60fps”,实际可能掉帧、卡顿、失焦时还在跑。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
结合时间戳做匀速动画(避免帧率依赖)
直接累加像素值(如 x += 2)会导致不同设备/负载下速度不一致。正确做法是根据上一帧到当前帧的时间差计算位移:
- 记录上一帧的时间戳
- 用
deltaTime = now - lastTime得出已过去毫秒数 - 按目标速度(如 100px/s)换算成本次应移动距离:
distance = speed * deltaTime / 1000
这样即使某帧卡住20ms,下一次会自动补上,视觉上保持匀速。
与定时器对比的关键优势
自动节流:页面切到后台或标签页不可见时,requestAnimationFrame 自动暂停,而 setTimeout 仍会触发,浪费资源甚至导致“醒来后疯狂补帧”;
精准对齐刷新:浏览器把你的绘制操作安排在 repaint 前,减少 layout thrashing 和强制同步布局;
更优调度策略:内部可能合并多个 rAF 调用、配合 GPU 渲染管线,比 JS 定时器更底层、更高效。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










