requestAnimationFrame详解

1、什么是requestAnimationFrame
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

简单来说,requestAnimationFrame 就是约定在下一次浏览器刷新前执行的一个定时器。类似setTimeout

requestAnimationFrame特点

  1. requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,如果系统绘制率是 60Hz,那么回调函数就会16.7ms再 被执行一次,如果绘制频率是75Hz,那么这个间隔时间就变成了 1000/75=13.3ms。换句话说就是,requestAnimationFrame的执行步伐跟着系统的绘制频率走。它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。
  2. 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
  3. requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
//注册
var id= window.requestAnimationFrame(callback);

//取消
window.cancelAnimationFrame(id)

        var btn = document.getElementById('btn')  
        var btnLength = 200
        var raf
        var btnFn = function(){
            btnLength++
            btn.style.width = btnLength + 'px'
            if (btnLength === 1000) {
                cancelAnimationFrame(raf)
            }else{
                raf = requestAnimationFrame(btnFn)
            }
        }
        raf = requestAnimationFrame(btnFn)

requestAnimationFrame详解_第1张图片

使用 requestAnimationFrame 替换 setTimeout 和 setInterva 可提升web性能。

setTimeout 和 setInterva 实现动画的缺点

  • 时间不精确,通常实际执行时间都要比其设定的时间晚一些。
  • 实现的动画在某些低端机上会出现卡顿、抖动的现象。(不同设备的屏幕刷新频率不同,而 setTimeout 和 setInterva 只能设置一个固定的时间间隔,这个时间和屏幕的刷新时间不同时,就会出现掉帧,而导致页面卡顿、抖动)


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

 使用场景:

  • 动画效果

当需要实现平滑的动画效果时,requestAnimationFrame是一个理想的选择。通过使用requestAnimationFrame,可以在每个浏览器刷新帧之前更新动画的状态,并在合适的时机进行渲染。这样可以确保动画的流畅性,并减少不必要的渲染操作。例如,实现平滑的过渡效果、动态的图表展示等都可以使用requestAnimationFrame来实现。

  • 平滑滚动


function scrollToTop() {
    const c = document.documentElement.scrollTop || document.body.scrollTop;
    if (c > 0) {
        window.requestAnimationFrame(scrollToTop);
        window.scrollTo(0, c - c / 8);
    }
}
  • 大量数据的渲染

比如一百万条数据的渲染,使用 requestAnimationFrame 分页加载,避免页面发生卡顿

//需要插入的容器
let ul = document.getElementById('container')
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
function loop(curTotal,curIndex) {
  if (curTotal <= 0) {
    return false
  }
  //每页多少条
  let pageCount = Math.min(curTotal, once)
  window.requestAnimationFrame(function () {
    for (let i = 0; i < pageCount; i++) {
      let li = document.createElement('li')
      li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
      ul.appendChild(li)
    }
    loop(curTotal - pageCount, curIndex + pageCount)
  })
}
loop(total, index)

你可能感兴趣的:(前端,javascript,开发语言)