Skip to content
On This Page

requestAnimationFrame()

1. 引言

requestAnimationFrame 是浏览器提供的用于在下一次重绘之前执行指定回调函数的 API。它通常用于创建流畅的 JavaScript 动画,能自动与浏览器的刷新率同步(通常是 60Hz,即约 16.6ms 执行一次)。

2. 工作原理

  • 浏览器每帧都会执行“重绘”操作(例如改变元素位置、样式)。
  • requestAnimationFrame 将回调放入一个队列,在每一帧的绘制之前执行该回调。
  • 如果回调中再次调用 requestAnimationFrame,就会形成递归循环,持续与屏幕刷新频率保持一致。

3. 与 setTimeout / setInterval 的区别

对比维度requestAnimationFramesetTimeout/setInterval
执行时机帧开始前,由浏览器决定(与屏幕刷新同步)宏任务队列,按指定延迟执行,与帧无关
频率匹配显示器刷新率(通常 60fps)不可控,即使设为 16.6ms,也可能因事件队列阻塞而漂移
性能页面隐藏/非激活时自动暂停,节省 CPU/电量后台依然执行,浪费资源
丢帧处理浏览器会自动合并同帧内的多次 DOM 修改容易丢帧或产生无效更新
精确性高(基于 vsync 信号)低(受事件循环影响,最小延迟约 4ms)

4. 优点(为什么用 rAF 做动画)

  • 流畅:与刷新率同步,避免掉帧或过度绘制。
  • 高效:页面不可见时自动停止,不消耗资源。
  • 精准时间戳:回调参数 timestamp 为高精度时间,可用于计算帧间差值。
  • 批量更新:浏览器可以合并同一帧内的样式计算和布局,减少重排。

5. 使用场景

  • JavaScript 动画:如移动、缩放、渐变等高频属性修改。
  • Canvas/WebGL 渲染:游戏、粒子效果、实时图表。
  • 滚动监听优化:配合滚动事件实现平滑视差效果。
  • 帧率监测:计算 FPS。
  • setTimeout 组合实现限流:例如在 rAF 中做 DOM 批量更新。

6. 注意事项 / 潜在缺点

  • 需要递归调用:不像 setInterval 自动重复,必须手动在回调末尾再次调用。
  • 不适合低频率任务:例如每隔几秒请求数据,应使用 setInterval
  • 兼容性:IE10 及以上均支持,旧版需降级(setTimeout 回退)。
  • 高频率回调:如果回调执行时间超过 16.6ms,会导致丢帧,需优化代码。