requestAnimationFrame

requestAnimationFrame介绍

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

语法:

window.requestAnimationFrame(callback);

参数:

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

返回值:

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

 如何使用?



    

    
        
        
        
    

可以看到,控制台成功的输出了一次  。 

requestAnimationFrame_第1张图片

 但是它只执行了一次,怎么做动画呢?别急,再看看 MDN 怎么说。

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

改下JS

window.onload = function () {
  var n = 0;
  function test() {
      n++;
      console.log("requestAnimationFrame ----", n);
      requestAnimationFrame(test);
  }
  requestAnimationFrame(test);
}

 requestAnimationFrame_第2张图片

执行频率 

回调函数执行次数通常是每秒60次,但在大多数遵循W3C建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。 

 即不用手动设置执行间隔时间,而是根据 浏览器屏幕刷新次数 自动调整了,也就是说浏览器屏幕刷新多少次,它就执行多少次。

回调函数参数

在同一个帧中的多个回调函数,它们每一个都会接受到一个相同的时间戳,即使在计算上一个回调函数的工作负载期间已经消耗了一些时间。该时间戳是一个十进制数,单位毫秒,最小精度为1ms(1000μs)。

function test(timeStamp) {
  console.log("requestAnimationFrame ----", timeStamp);
  requestAnimationFrame(test);
}
requestAnimationFrame(test);

requestAnimationFrame_第3张图片

 可以看出每次执行隔间时间戳近似等于 1000 / 60 = 16.666毫秒

如果有多个requestAnimationFrame一起执行会怎样?

function test1(timeStamp) {
  console.log("requestAnimationFrame1 ----", timeStamp);
  requestAnimationFrame(test1);
}
function test2(timeStamp) {
  console.log("requestAnimationFrame2 ----", timeStamp);
  requestAnimationFrame(test2);
}
requestAnimationFrame(test1);
requestAnimationFrame(test2);

requestAnimationFrame_第4张图片

可以看到,两个 requestAnimationFrame 在控制台输出的时间戳是一样的。也就是浏览器刷新一次的时候,执行所有的 requestAnimationFrame ,并且它们的回调参数是一模一样的。

浏览器优化

为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame() 运行在后台标签页或者隐藏的