美文网首页
raf 和 setTimeout 区别

raf 和 setTimeout 区别

作者: 菜鸡前端 | 来源:发表于2021-08-31 14:43 被阅读0次

MDN 文档中,对 requestAnimationFrame 介绍是:告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。根据宏任务和微任务的定义,显然 requestAnimationFrame 属于宏任务。

1. 先说 raf 优点

1.1 提高性能和电池寿命

为了提高性能和电池寿命,因此在大多数浏览器里,当 requestAnimationFrame() 运行在后台标签页或者隐藏的<iframe> 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。

1.2 raf 执行频率和系统保持一致

raf 的执行步伐跟着系统的绘制频率走,它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。前提是保证浏览器的“绘制任务”没有被阻塞,另外回调函数本身没有耗时任务。

2. 使用 raf 也能写出很卡的动画

下面使用 raf 来做动画很卡,是因为 raf 的回调函数中有耗时长任务。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>requestAnimateFrame</title>
  <style>
    #box {
      width: 100px;
      height: 100px;
      border: 1px solid red;
    }
  </style>
</head>

<body>
  <div id="box"></div>
</body>
<script>

  function nextTick(fn) {
    window.requestAnimationFrame(fn);
  }

  function longTask() {
    var sum
    for (let i = 0; i < 10000000; i++) {
      sum += i * Math.random();
    }
    return sum
  }

  var box = document.querySelector("#box");
  var ml = 0;
  function animate(timestamp) {
    time = Date.now()
    if (ml > 200) {
      return
    }
    ml += 10;
    longTask();
    box.style.marginLeft = `${ml}px`;
    nextTick(animate);
  }

  animate()
</script>
</html>

3. raf 的回调函数什么时候执行

从表现来看,raf 任务,也需要等宏任务执行之后完成之后,再执行。

  function longTask() {
    var s = Date.now();
    var sum = 0;
    for (let i = 0; i < 100000000; i++) {
      sum += i;
    }
    console.log('longTask spend', Date.now() - s);
  }

  var t = Date.now()
  window.requestAnimationFrame(function (timestamp) {
    console.log('raf callback start', Date.now() - t)
    console.log("timestamp", timestamp)
  })
  longTask()

// longTask spend 101
// raf callback start 102
// timestamp 8.685

4. raf 和 setTimeout (60帧) 本质区别

这里我抛出一个问题,如何写代码去验证两者的区别,如果你能写出代码来验证两者的明显区别,麻烦你在评论区留言。

setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔,参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。

requestAnimationFrame 采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果

4.1 raf

requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API

  • setInterval、setTimeout 是开发者主动要求浏览器去绘制,但是由于种种问题,浏览器可能会漏掉部分命令
  • requestAnimationFrame 就是浏览器什么要开始绘制了浏览器自己知道,通过requestAnimationFrame 告诉开发者,这样就不会出现重复绘制丢失的问题了

4.2 raf 和 setTimeout 区别

  1. requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧
  2. 隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

相关文章

网友评论

      本文标题:raf 和 setTimeout 区别

      本文链接:https://www.haomeiwen.com/subject/hesziltx.html