requestAnimationFrame详解及对比

 

目录

1、什么是requestAnimationFrame 

2、 设置这个API的目的是什么? 

3、 requestAnimationFrame的优缺点 

①优点: 

②缺点: 

4、 requestAnimationFrame的使用 

①语法: 

②范例: 

5、setTimeout(补充) 

 

 

1、什么是requestAnimationFrame

requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘,让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

在运行过程中,window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

 

注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()

 

2、设置这个API的目的是什么?

用js来实现动画,一般是用setTimeout或setInterval这两个函数。css3动画出来后,实现动画的方式又多了一种选择,而且性能和流畅度也得到了很大的提升。

但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。但是setTimeout和setInterval有着严重的性能问题,就算现代浏览器对其极力优化,但还是无法跟css3的动画性能相提并论。

 

 

有需求就会有市场,有痛点就会有想要去解决

 

requestAnimationFrame 是一个专门为实现高性能的帧动画而设计的API,目前不管是移动端还是桌面端,新版本的浏览器都已经支持了这个API。

3、requestAnimationFrame的优缺点

(相对于setTimeout、setInterval)

 

①优点:

  • requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。充分利用了显示器的刷新机制,比较节省系统资源(显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次)。
  • requestAnimationFrame是一个全局函数。调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘,它会接收一个回调函数作为参数,在浏览器即将开始重绘时,会调用这个函数,并会给这个函数传入调用回调函数时的时间作为参数。之后会反复不断地调用requestAnimationFrame,以达到动画效果;
  • 节省了CPU、GPU和电力。使用setTimeout实现的动画,当页面被隐藏或最小化时,setTimeout 仍然在后台执行动画任务,此时刷新动画是没有意义的,完全是浪费CPU等资源。而requestAnimationFrame则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU、GPU和电力开销。

 

②缺点:

  • 由于requestAnimationFrame目前还存在兼容性问题,而且不同的浏览器还需要带不同的前缀。因此需要通过降级的方式对requestAnimationFrame进行封装,根据不同浏览器的情况从高级特性往低进行回退。
  • requestAnimationFrame是在主线程上完成。这意味着,如果主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。

 

4、requestAnimationFrame的使用

 

①语法:

window.requestAnimationFrame(callback);

 

参数:callback

下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。该回调函数会被传入DOMHighResTimeStamp参数,该参数与performance.now()的返回值相同,它表示requestAnimationFrame() 开始去执行回调函数的时刻。

返回值:

一个 long 整数,请求 ID ,是回调列表中唯一的标识。是个非零值,没别的意义。你可以传这个值给 window.cancelAnimationFrame() 以取消回调函数。

 

②范例:

var start = null;var element = document.getElementById('SomeElementYouWantToAnimate');

element.style.position = 'absolute';

function step(timestamp) {

  if (!start) start = timestamp;

  var progress = timestamp - start;

  element.style.left = Math.min(progress / 10, 200) + 'px';

  if (progress < 2000) {

    window.requestAnimationFrame(step);

  }}



window.requestAnimationFrame(step);
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

(范例来源于MDN web docs)

 

 

5、setTimeout补充

setTimeout 是通过设置一个间隔时间来不断的改变图像的位置,从而达到动画效果的。但是利用seTimeout实现的动画在某些低端机上会出现卡顿、抖动的现象。

那为什么会出现卡顿呢

  1. setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。
  2. 刷新频率受屏幕分辨率屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。

以上两种情况都会导致setTimeout的执行步调和屏幕的刷新率不一致,从而出现掉帧现象。

 

那为什么步调不一致就会引起丢帧呢?

首先要明白,setTimeout的执行只是在内存中对图像属性进行改变,这个变化必须要等到屏幕下次刷新时才会被更新到屏幕上。如果两者的步调不一致,就可能会导致中间某一帧的操作被跨越过去,而直接更新下一帧的图像。

 

举个栗子:

假设屏幕每隔16.7ms刷新一次,而setTimeout每隔10ms设置图像向左移动1px, 就会出现如下绘制过程:

  • 第0ms: 屏幕未刷新,等待中,setTimeout也未执行,等待中;
  • 第10ms: 屏幕未刷新,等待中,setTimeout开始执行并设置图像属性left=1px;
  • 第16.7ms: 屏幕开始刷新,屏幕上的图像向左移动了1px, setTimeout 未执行,继续等待中;
  • 第20ms: 屏幕未刷新,等待中,setTimeout开始执行并设置left=2px;
  • 第30ms: 屏幕未刷新,等待中,setTimeout开始执行并设置left=3px;
  • 第33.4ms:屏幕开始刷新,屏幕上的图像向左移动了3px, setTimeout未执行,继续等待中;

从上面的绘制过程中可以看出,屏幕没有更新left=2px的那一帧画面,图像直接从1px的位置跳到了3px的的位置,这就是丢帧现象,这种现象就会引起动画卡顿。

(setTimeout解释大部分来源于百度,经过作者略微修改,仅供参考)

 

 

 

 

 

  • 20
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: `requestAnimationFrame` 是一个浏览器 API,它可以让你的 JavaScript 在下一个浏览器重绘之前运行。这样可以有效地提高动画的性能,因为它可以让浏览器在重绘之前知道你的动画需要做什么。使用`requestAnimationFrame`可以避免浏览器的重绘和回流,提高动画的流畅度。 使用方法: ``` // 定义动画函数 function animate() { // 在这里编写动画代码 requestAnimationFrame(animate); } // 开始动画 requestAnimationFrame(animate); ``` 注意:不同浏览器有不同的实现,如果不支持`requestAnimationFrame`,可以使用`setTimeout`或`setInterval`来模拟。 ### 回答2: requestAnimationFrame 是用来代替 setTimeout 或 setInterval 的一种优化方案,它可以让Javascript在浏览器的下一次重绘之前执行某个函数,以达到最佳的渲染效果。 它的优点在于可以让浏览器在渲染性能的限制下自动调整,以便保持每秒渲染帧率在60FPS左右,从而有效避免掉帧现象,一定程度上优化体验。 使用 requestAnimationFrame 的语法如下: window.requestAnimationFrame(callback); 其中,callback 是在下一帧渲染时要执行的函数,它会自动传入一些参数,例如时间戳等。 具体来说,requestAnimationFrame 的工作原理是这样的: 1. 当 Javascript 代码执行到 window.requestAnimationFrame() 时,会把回调函数放到一个队列里面等待执行。 2. 浏览器在下一次重绘之前会检查这个队列,如果队列里有函数,就执行这些函数,否则什么也不做。 3. 如果函数执行的过程中或执行完成后,将再次请求下一帧的重绘。 有了 requestAnimationFrame,我们就可以编写更加流畅自然的动画效果,而不必担心因为性能瓶颈导致掉帧,从而达到更好的用户体验。同时,它也可以有效避免由于 setInterval 或 setTimeout 过于频繁地操作Dom节点而引起的性能问题。不过值得注意的是,requestAnimationFrame 并不支持 IE9 及以下版本的浏览器,因此在进行兼容性考虑时需要引入 polyfill 或使用其他方案。 ### 回答3: requestAnimationFrame(简称RAF)是一种用于浏览器动画效果的方法。该方法通过以比setInterval更优秀的方式在浏览器下一次渲染时刻之前更新动画效果,以使动画流畅自然。在一些高要求的场景下,使用setTimeout和setInterval往往会导致更新不及时;而使用requestAnimationFrame可以保证效果在下一次渲染时完成,确保页面更新及时、不丢帧。 requestAnimationFrame的主要特点是: - 操作DOM次数减少,增强性能 - 优化页面动画,避免出现卡顿现象 - 适用于各种各样的动画效果 - 减少了原来程序需要处理时间,使得程序变得更加高效 requestAnimationFrame最大的优点是:在页面未找到其他的任务时,一次帧效果可以达到每秒60帧,基本上和显示器的刷新频率相匹配。此外,requestAnimaitonFrame会自动适应浏览器窗口大小的变化,并且可以在各种设备上正常工作。另外,requestAnimationFrame还可以在浏览器最小化、后台挂起等情况下暂停,以节省计算资源。 使用requestAnimationFrame的步骤如下: 1.调用requestAnimationFrame函数,并带有一个函数作为参数 2.在函数中改变元素属性或是Canvas的状态和图像/文本内容 3.使浏览器执行函数 使用requestAnimationFrame的方法一般都遵循“递归调用”的设计模式。就是说每次执行函数时都会加入下一个临界点循环,递归执行直到某个条件终止。 总之,requestAnimationFrame是一种比setTimeout更优秀的动画效果控制方法,其优点是高效、流畅,对于大多数的动画效果是一个很好的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值