事关我对于requestAnimationFrame的那些事

177 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

有关于requestAnimationFrame

写在前面: 这个api其实很早接触到了,但最近才正式开始使用,是跟浏览器性能和有关的,下面总结一下它的用法.

使用场景

  • 循环执行动画
export const scrollToTop = () => {
  const height = document.documentElement.scrollTop || document.body.scrollTop;
  if (height > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, height - height / 8);
  }
}
    

那同样的需求,使用settimeout和setinterval不也能实现么,这个api有什么特别的吗?有的,更优秀的性能就是它最大的特点.

优势

  • requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

  • 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流

也就是说,requestAnimationFrame的执行频率跟你的浏览器刷新频率会一直,可以保证一定是流畅的动画效果,同时第二个特性又能保证在不可见区域将不会无故消耗你的cpu,gpu和内存.

扩展

settimeout可以自定义时间间隔,且可以使用clearsettimeout随时销毁停止,requestAnimationFrame是否可以呢

  • requestAnimationFrame如何停止

requestAnimationFrame默认返回一个id , 可以在执行的时候保存好这个id , 而cancelAnimationFrame()接收一个参数 , cancelAnimationFrame只需要传入之前保存的id就可以停止了,类似clearsettimeout(timer);

let  id = window.requestAnimationFrame(() => {window.scrollTo(0,0)})

window.cancelAnimationFrame(id);

  • 如何改变requestAnimationFrame的间隔
// 加快间隔
没必要 默认频率通常是16ms一帧 肉眼已经看不出区别了 基本已经最快了

// 降低间隔
像我们上面那个回到顶部的函数 , 使用的是递归调用 , 在页面高度大于0的情况下一直递归调用自身 , 每次上抬8个像素直到归零 , 我想到的方式 , 可以通过时间戳判断差值 , 每次执行完保留当前时间戳 , 下次执行前判断上一次执行时间戳与当前时间戳的差值是否大于你规定的间隔,满足则成功执行逻辑 , 否则到下一次判断.
                                                                     

End