简介
requestAnimationFrame
是浏览器提供的一个用于优化动画渲染的 API。它可以让浏览器在下一次重绘之前调用指定的回调函数来更新动画,从而确保动画的流畅性和性能。
为什么需要 requestAnimationFrame?
在传统的 JavaScript 动画实现中,我们通常使用 setTimeout
或 setInterval
来控制动画的执行。但这种方式存在以下问题:
- 无法确保回调函数的执行时机与浏览器的重绘时间同步
- 可能造成掉帧或不必要的重绘
- 在标签页不可见时仍会执行,浪费系统资源
基本用法
function animate() {
// 更新动画
element.style.transform = `translateX(${position}px)`;
position += 2;
// 继续下一帧动画
requestAnimationFrame(animate);
}
// 开始动画
requestAnimationFrame(animate);
优势特点
同步刷新率:自动适应显示器刷新率,保证最佳的动画效果
节能环保:当页面不可见时(如切换标签页),会自动暂停执行
性能优化:浏览器会对多个
requestAnimationFrame
回调进行优化,集中在一次重绘中完成精确时间控制:回调函数会接收到一个精确的时间戳参数
进阶使用
1. 时间控制
let start = null;
function animate(timestamp) {
if (!start) start = timestamp;
const progress = timestamp - start;
// 动画持续3秒
if (progress < 3000) {
element.style.transform = `translateX(${progress/10}px)`;
requestAnimationFrame(animate);
}
}
2. 取消动画
const animationId = requestAnimationFrame(animate);
// 需要时可以取消动画
cancelAnimationFrame(animationId);
兼容性处理
const requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
最佳实践
- 控制帧率:不是每一帧都需要执行动画,可以根据时间戳来控制
let lastTime = 0;
function animate(timestamp) {
if (timestamp - lastTime > 100) { // 每100ms执行一次
// 执行动画
lastTime = timestamp;
}
requestAnimationFrame(animate);
}
避免递归调用:在动画结束时要记得停止
使用性能监控:可以通过 Performance API 监控动画性能
注意事项
- 不要在回调函数中执行耗时操作
- 注意内存泄漏,及时清理不需要的动画
- 合理使用
cancelAnimationFrame
- 考虑移动设备的性能限制
总结
requestAnimationFrame
是现代网页动画的重要工具,它提供了更好的性能和用户体验。合理使用这个 API 可以帮助我们创建流畅的动画效果,同时避免不必要的性能消耗。