requestNextAnimationFrame

定义

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

  • 下次重绘之前?

原理

  • 一般显示器都是 60Hz 的刷新率,即 1000ms 内刷新 60 次,每 16.7 毫秒刷新 1 次。rAF 的执行时机则是由系统来决定,(60Hz-->16.7ms / 75Hz-->13.3ms),rAF 的执行步伐跟着系统的绘制频率走。它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。

和 setTimeout 的区别

  • 执行时机

  • 自动休眠

  • See the Pen jONBMMz by Ted.SZ (@tedsz1025) on CodePen.

  • image

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

    • 0ms: 未刷新,等待中,未执行;

    • 10ms:未刷新,等待中,执行设置 left=1px;

    • 16.7ms:刷新,图像向左移动 1px,未执行;

    • 20ms:未刷新,等待中,执行设置 left=2px;

    • 30ms: 未刷新,等待中,执行设置 left=3px;

    • 33.4ms: 刷新,图像向左移动 3px,未执行;

    • ...

  • image

  • image

rAF 使用场景

  • 保障动画流畅执行

  • 完成一些 CSS 不能完成的动画

  • 保证图片渲染完成(连续调用两次)

项目中的使用

function Dom__onNextFrame(callback) {
  // 需要两次确保一定是下一次渲染
  var nextFrame = requestAnimationFrame;
  var frameCount = 2;
  return next();

  function next() {
    nextFrame(function() {
      if (--frameCount) {
        return next();
      }

      callback();
    });
  }
}

实例

<img
  id="img"
  src="http://www.zmdz.com/bbs/incomefiles/20121/3110484797916.JPG"
  style="width: 300px; height:300px; border: 1px solid red;"
  onload="Dom__onNextFrame()"
/>
<div>step: <span id="step">waiting...</span></div>

<script>
  var stepEl = document.querySelector('#step');
  var img = document.querySelector('#img');

  function Dom__onNextFrame() {
    var frameCount = 2;
    return next();

    function next() {
      requestAnimationFrame(function() {
        alert('rAF');
        if (--frameCount) {
          return next();
        }

        changeStatus();
      });
    }

    function changeStatus() {
      stepEl.innerText = 'img loaded.';
      console.log('img loaded.');
    }
  }
</script>
  • image

  • image

Last updated

Was this helpful?