requestAnimationFrame
是浏览器提供的一项高性能动画 API,用于在浏览器重绘(repaint)或重排(reflow)之前执行动画帧。它通过与屏幕刷新率(通常为 60Hz,即每秒 60 次)同步,确保动画流畅且高效,同时减少不必要的计算,是现代前端开发中实现动画的最佳实践。
核心原理
- 与屏幕刷新率同步:
每次浏览器重绘屏幕前,requestAnimationFrame
会调用你传入的回调函数,确保动画帧率 与屏幕刷新率一致(通常 60 FPS,即每秒 60 帧)。
- 节省资源:
当页面被隐藏(如切换到后台标签)时,浏览器会自动暂停 requestAnimationFrame
的调 用,避免浪费资源。
- 替代传统定时器
相比 setTimeout
/setInterval
,rAF 自动匹配设备刷新率,避免因主线程阻塞导致的卡顿 或丢帧问题
- 自动优化:
浏览器会智能调整动画帧率。例如,在高负载时降低帧率,保证性能;在低负载时保持高 帧率。
基本用法
1. 基础语法
const requestId = requestAnimationFrame(callback);
callback
:执行动画帧的函数,参数为时间戳(单位:毫秒,相对于performance.now()
)。requestId
:唯一标识符,用于取消请求。
2. 取消请求
cancelAnimationFrame(requestId);
3.动画循环
需在回调函数中递归调用 以维持动画循环
浏览器会批量处理多个 requestAnimationFrame
调用,确保同一帧内所有动画更新只触发一次重绘。
确保 requestAnimationFrame
在回调中递归调用,否则动画会执行一次后停止。
function animate(timestamp) {
const deltaTime = timestamp - lastTime;
// 基于 deltaTime 更新动画状态
lastTime = timestamp;
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
4.与 setTimeout/setInterval 的对比
维度 | requestAnimationFrame | setTimeout/setInterval |
---|---|---|
执行时机 | 屏幕刷新前同步执行,避免丢帧 | 固定时间间隔,易受主线程阻塞影响导致延迟 |
帧率控制 | 自动匹配屏幕刷新率(如 60Hz) | 需手动计算时间间隔(如 16.67ms),难以精准匹配 |
后台运行 | 页面隐藏时自动暂停,节省资源 | 持续执行,浪费 CPU/GPU 资 |
性能优化 | 浏览器合并同帧内的多次更新,减少重复渲染 | 无优化,频繁触发可能导致性能瓶颈 |