帧数、刷新率、requestAnimationFrame、requestIdleCallback

帧数(Frames Per Second)

显卡在每一秒所传输的图片的数量,也有人称之为显卡刷新率,用fps来表示。

刷新率

指显示器在每秒钟内刷新画面的次数 hz。

理想情况是帧数≈刷新率:

  • 假如帧数>刷新率,无效帧过多,会导致画面被撕裂感(如同时显示上一帧的上半图+下一帧的下半图)。
    此时可以使用* 垂直同步:强制显卡等待显示器完成当前刷新周期,再输出下一帧,从而使帧率(FPS)与显示器刷新率(Hz)同步。
  • 假如刷新率>帧数,就会导致图片数量不够,一张图片重复刷新形成掉帧(Frame Drop)。

setTimeout/setInterval在动画中困境

  1. 计时器处于异步队列中,会等待主线程执行完毕后再执行,因此实际执行时间一般要比设定时间晚一些。
  2. 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同。

一般为计时器设置16.7ms的间隔以同步60Hz刷新频率,但由于以上原因,都可能造成频率不一致而丢帧。

requestAnimationFrame

requestAnimationFrame要求浏览器在下次重绘发生之前调用回调函数。

  • requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态(如最小化),或处于隐藏的iframe时,动画会自动暂停,有效节省了CPU开销
  • 通常每秒触发60次,但在高刷新率的屏幕中会更频繁触发,通常通过计算每次调用的间隔来控制实际动画速度
const element = document.getElementById('some-element-you-want-to-animate');
let start;

function step(timestamp) {
  if (start === undefined)
    start = timestamp;
  const elapsed = timestamp - start;

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

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

window.requestAnimationFrame(step);
  • 返回值可用于取消该定时器
var timer = requestAnimationFrame(function(){
    console.log(0);
}); 
cancelAnimationFrame(timer);

requestIdleCallback

  • requestIdleCallback 在每次屏幕刷新并且空闲(即处理完宏任务+requestAnimationFrame等依然有空闲)时加入调用队列(在requestAnimationFrame之后加入)
    requestIdleCallback(fn,{timeout:1000})即在下次刷新且空闲时加入调用队列,且最迟在1s后加入
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容