requestAnimationFrame详解:原理、优势与实战应用

作者:听澜

时间:2026-11-01

浏览:362

本文深入解析requestAnimationFrame API,阐述其作为浏览器宏任务在重绘前调用的机制。对比CSS3动画与JS动画的优劣,详细分析setTimeout与setInterval在动画实现中的缺陷,如丢帧、资源浪费等。重点介绍requestAnimationFrame在节能、函数节流及高频率事件处理中的优势,并结合滚动监听与大数据渲染场景提供实战建议。

文章目录

1.定义

requestAnimationFrame是浏览器提供的一个宏任务。其调用方式与setTimeout、setInterval类似,但无需手动指定时间间隔。该方法接收一个回调函数作为参数,该回调会在浏览器下一次重绘之前被触发执行。它返回一个整数类型的动画帧ID,此ID可用于调用cancelAnimationFrame来取消该动画的执行。

2.特点

requestAnimationFrame的主要特点如下:

【1】requestAnimationFrame会将每一帧内的所有DOM操作合并处理,确保在一次重绘或回流中完成,且重绘或回流的时间间隔严格跟随浏览器的屏幕刷新频率。

【2】当元素处于隐藏或不可见状态时,requestAnimationFrame不会触发重绘或回流,从而显著降低CPU、GPU及内存的占用。

【3】该API由浏览器专为动画场景设计,运行时会自动优化调用过程。若页面未处于激活状态,动画会自动暂停,从而有效节省CPU资源。

3.浏览器动画原理

理解requestAnimationFrame的优势需先掌握浏览器动画的基本实现逻辑。前端通过频繁触发一个函数来更新物体的位置属性(例如每次沿X轴增加1)。当触发频率足够高时,人眼无法察觉间隔,从而呈现出流畅的动画效果。

4. CSS3动画和JS动画的比较

·CSS动画优点

【1】在基于Chromium内核的浏览器中表现良好。

【2】CSS动画通常不触发layout或paint操作。但若CSS或JS动画触发了paint或layout,main thread需重新计算Layer树,此时两者均会阻塞后续操作。

【3】在部分场景下,浏览器可对动画进行优化,例如专门创建新图层来运行动画。

【4】部分效果可强制启用硬件加速,利用GPU提升动画性能。

·CSS动画缺点

【1】代码编写较为冗长。

【2】实现稍复杂的动画时,CSS代码可能变得笨重,且运行过程中的控制能力较弱。

【3】CSS3动画仅在特定场景下支持暂停与继续,且无法在动画的特定位置添加回调函数。

·JS动画优点

【1】JS动画具备强大的控制能力,可在播放过程中对动画进行精细控制,包括开始、暂停、终止及取消等操作。

【2】JS动画效果比CSS3更丰富,功能覆盖面广,可实现曲线运动、冲击闪烁、视差滚动等CSS难以实现的效果。

【3】JS动画在大多数情况下不存在兼容性问题,而CSS3动画则存在一定的兼容挑战。

·JS动画缺点

【1】JS在浏览器主线程中运行,而主线程还需处理其他JS脚本、样式计算、布局及绘制任务。若受干扰导致线程阻塞,可能引发丢帧现象。

【2】对于帧率表现不佳的低版本浏览器,CSS3可实现自然降级,而JS动画需额外编写兼容代码。

【3】JS动画通常需频繁操作DOM的CSS属性以实现视觉效果,导致浏览器不断执行重绘和重排,性能消耗巨大,尤其在移动端内存受限的情况下更为明显。

5. setTimeout 、setInterval、requestAnimationFrame区别

1》setInterval

运行机制:

按照指定的周期(毫秒计)调用函数或计算表达式。该方法会持续调用函数(即使页面被隐藏或最小化,setInterval仍在后台执行,这种无意义的刷新对CPU是极大浪费),直到调用clearInterval()或窗口关闭。setInterval的执行时间不确定,参数中的时间间隔仅表示将代码加入异步队列等待的时间。只有当主线程任务及队列前序任务执行完毕后,动画代码才会真正执行。

缺点:

(1)setInterval()无视代码错误,若执行的代码出错,它仍会持续调用该代码。

(2)setInterval无视网络延迟。由于服务器过载、断网、流量激增或带宽受限等原因,请求耗时可能远超预期,但setInterval仍按固定间隔触发请求,最终导致客户端网络队列拥堵。

(3)setInterval不保证执行。与setTimeout不同,它无法保证在设定的时间间隔后代码一定执行。若调用函数耗时过长,某些调用会被直接忽略。

2》setTimeout

运行机制:

在指定的毫秒数后调用函数或计算表达式。每次函数执行都会创建一个新的定时器。在前一个定时器代码执行完毕前,不会向队列插入新的定时器代码,从而确保没有缺失的间隔,并保证在下一次执行前至少等待指定的间隔,避免连续运行。方法执行完成后定时器即停止(虽存在但已无用)。

缺点:

(1)利用setTimeout实现的动画在低端设备上可能出现卡顿、抖动现象。

(2)setTimeout的执行时间并不确定。在JS中,setTimeout任务被放入异步队列,只有当主线程任务执行完毕后,才会检查队列中的任务是否需执行,因此实际执行时间通常晚于设定时间。

(3)刷新频率受屏幕分辨率和尺寸影响,不同设备的屏幕刷新率可能不同,而setTimeout只能设置固定时间间隔,该间隔未必与屏幕刷新时间一致。

(4)setTimeout的执行仅在内存中改变图像属性,此变化需等待屏幕下次刷新时才更新至屏幕。若两者步调不一致,可能导致中间某帧操作被跳过,直接更新下一帧图像。

3》requestAnimationFrame

缺点:requestAnimationFrame不管理回调函数。若在回调执行前多次调用带有同一回调函数的requestAnimationFrame,会导致该回调在同一帧中执行多次。

解决办法:针对此类高频事件,一般解决方法是使用节流函数。但在此场景下,使用节流函数无法完美解决问题,因为节流是通过时间管理队列的。更完美的方案是通过requestAnimationFrame管理队列,即保证requestAnimationFrame队列中相同的回调函数只有一个。

1.定义

4》与setTimeout和setInterval的区别

【1】执行次数:setInterval执行多次,setTimeout、requestAnimationFrame执行一次。

【2】性能:setTimeout可能出现丢帧、卡顿,setInterval可能出现调用丢失,而requestAnimationFrame不会遇到这些问题。页面未激活时不执行动画,大幅减少CPU消耗。

【3】兼容性问题:setInterval、setTimeout在IE浏览器中不支持参数传递,但能在大多数浏览器中正常使用。requestAnimationFrame不兼容IE10以下版本。

5》requestAnimationFrame补充

除上述优势外,requestAnimationFrame还有以下两点优势:

【1】CPU节能:使用setTimeout实现的动画,当页面隐藏或最小化时,setTimeout仍在后台执行动画任务。由于页面不可见或不可用,刷新动画无意义且浪费CPU资源。而requestAnimationFrame则不同,当页面未激活时,系统会暂停屏幕刷新任务,跟随系统步伐的requestAnimationFrame也会停止渲染;当页面激活时,动画从上次停留处继续执行,有效节省CPU开销。

【2】函数节流:在高频率事件(如resize、scroll)中,为防止在一个刷新间隔内多次执行函数,使用requestAnimationFrame可保证每个刷新间隔内函数仅执行一次。这既保证了流畅性,又节省了函数执行的开销。一个刷新间隔内多次执行并无意义,因为显示器每16.7ms刷新一次,多次绘制不会在屏幕上体现出来。

5.应用场景

【1】监听 scroll 函数:页面滚动事件(scroll)的监听函数非常适合使用此API,将其推迟到下一次重新渲染时执行。

1.定义

【2】大量数据渲染:例如对十万条数据进行渲染,主要可采用以下方法:

(1)使用定时器

1.定义

(2)使用 requestAnimationFrame

1.定义

【3】监控卡顿方法:每秒计算一次网页的FPS(帧率),获取数据列进行分析。通俗而言,通过requestAnimationFrame API定时执行JS代码,若浏览器卡顿导致无法保证渲染频率,1秒内frame数无法达到60帧,即可间接反映浏览器的渲染帧率。

1.定义

总结

本文介绍了requestAnimationFrame请求动画帧的核心内容,更多相关requestAnimationFrame请求动画帧内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章