是什么

requestAnimationFrame

window.requestAnimationFrame() 方法跟 setTimeout 类似,都是推迟某个函数的执行。不同之处在于,setTimeout 必须指定推迟的时间,window.requestAnimationFrame() 则是推迟到浏览器下一次重流时执行,执行完才会进行下一次重绘。重绘通常是 16 ms 执行一次,不过浏览器会自动调节这个速率,比如网页切换到后台 Tab 页时,requestAnimationFrame() 会暂停执行。

如果某个函数会改变网页的布局,一般就放在 window.requestAnimationFrame() 里面执行,这样可以节省系统资源,使得网页效果更加平滑。因为慢速设备会用较慢的速率重流和重绘,而速度更快的设备会有更快的速率。

示例

在这个例子中,一个元素的动画时间是 2 秒(2000 毫秒)。该元素以 0.1px/ms 的速度向右移动,所以它的相对位置(以 CSS 像素为单位)可以通过动画开始后所经过的时间(以 毫秒)的函数来计算 0.1 * elapsed。该元素的最终位置是在其初始位置的右边 200px(0.1 * 2000)。

const element = document.getElementById("some-element-you-want-to-animate");
let start, previousTimeStamp;
let done = false;
 
function step(timestamp) {
  if (start === undefined) {
    start = timestamp;
  }
  const elapsed = timestamp - start;
 
  if (previousTimeStamp !== timestamp) {
    // 这里使用 Math.min() 确保元素在恰好位于 200px 时停止运动
    const count = Math.min(0.1 * elapsed, 200);
    element.style.transform = `translateX(${count}px)`;
    if (count === 200) done = true;
  }
 
  if (elapsed < 2000) {
    // 2 秒之后停止动画
    previousTimeStamp = timestamp;
    if (!done) {
      window.requestAnimationFrame(step);
    }
  }
}
 
window.requestAnimationFrame(step);

扩展阅读