requestAnimationFrame 与 setInterval

requestAnimationFrame

window.requestAnimationFrame()要求浏览器在下次重绘之前调用指定的回调函数更新动画。如果想在浏览器下一次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()

// requestAnimationFrame
const el = document.getElementById("box");
let start;

function step(timestamp) {
  if (start === undefined) start = timestamp;

  const elapsed = timestamp - start;

  // 这里使用`Math.min()`确保元素刚好停在200px的位置
  el.style.transform = `translateX(${Math.min(0.1 * elapsed, 200)}px)`;

  if (elapsed < 2000) { // 两秒后停止动画
    window.requestAnimationFrame(step);
  }
}

window.requestAnimationFrame(step);

setInterval

// setInterval
const el = document.getElementById('box');
let px = 0;
let t = null

function step () {
  px++;

  el.style.transform = `translateX(${ px }px)`;

  if (px >= 200) {
    clearInterval(t);
  }
}

t = setInterval(step, 1000 / 60);

两者对比

  • 布局绘制逻辑不同
    • setInterval:回调逻辑存在多次 DOM 操作,就会进行多次计算、绘制
    • requestAnimationFrame:把所有DOM 操作集中起来,一次性进行统一计算、统一绘制,性能较好
  • 窗口最小化时,运行情况不同
    • setInterval:一直执行回调函数
    • requestAnimationFrame:最小化时,暂停程序执行;页面打开时,从暂停的位置重新开始
  • 是否导致无意义的回调执行,重绘重排
    • setInterval(step, 0):导致多次无意义的回调执行(计时间隔小于刷新率,无意义)
    • requestAnimationFrame:只会在下次重绘时执行

> cd ..