requestAnimationFrame(简写为rAF)之所以在性能上优于setInterval或setTimeout,主要有以下几个原因:
1. 浏览器优化
requestAnimationFrame是专门为动画设计的API,浏览器知道您通过这个函数请求的回调是用于绘制动画的。因此,浏览器可以对动画进行优化,包括减少在不可见标签页中的动画的帧率,或者是在动画不在屏幕上时停止动画,这样可以提高性能并减少能耗。
2. 屏幕刷新率同步
requestAnimationFrame回调执行的频率通常与浏览器的屏幕刷新率同步。大多数屏幕有60Hz的刷新率,意味着屏幕每秒刷新60次。rAF会尽可能匹配这个频率,每次屏幕刷新时更新一次动画,从而创建平滑的视觉效果。而setInterval和setTimeout则没有这样的机制,可能会导致动画出现掉帧,或者动画更新与屏幕刷新不同步,造成不必要的计算和屏幕撕裂。
3. 减少页面重排和重绘
使用requestAnimationFrame进行动画处理,浏览器可以将动画的视觉更新和DOM更新安排在同一个浏览器的绘制周期内,这样可以减少页面重排(layout)和重绘(repaint)的次数,提高性能。
4. CPU节能
当使用setInterval或setTimeout时,如果设定的时间间隔很短,即使元素不可见,它们也会继续运行,这将不必要地占用CPU资源。requestAnimationFrame会智能调整,当用户切换到其他标签或最小化窗口时,动画会暂停,这有助于减少CPU消耗,特别是在移动设备上。
示例
考虑一个简单的动画例子,比如一个元素的左右滑动。使用setInterval可能会这样编写代码:
javascriptlet position = 0; setInterval(function() { position += 5; element.style.transform = `translateX(${position}px)`; }, 16); // 大约对应60Hz刷新率的间隔
这段代码会尝试每16毫秒移动元素,但没有机制确保它与屏幕刷新同步。
而使用requestAnimationFrame,代码如下:
javascriptlet position = 0; function step() { position += 5; element.style.transform = `translateX(${position}px)`; requestAnimationFrame(step); } requestAnimationFrame(step);
这里,动画逻辑与浏览器的刷新率同步,能够根据屏幕刷新情况智能调整执行频率。
综上所述,requestAnimationFrame提供了更高效、更平滑的动画体验,尤其是对于复杂或高性能需求的动画,这比使用setInterval或setTimeout要好得多。