- 帧数,就是显卡在每一秒所传输的图片的数量,也有人称之为显卡刷新率,用fps来表示。
- 刷新率,则是指显示器在每秒钟内刷新画面的次数 hz
假如帧数很高,但刷新率低,无效帧过多,会导致画面被撕裂感。
假如刷新率高,但是帧数低,就会导致图片数量不够,一张图片重复刷新形成卡顿。因此需要尽可能保证显卡帧数与屏幕刷新率的一致。
- 垂直同步,可以让显示器延迟输入画面等待显卡渲染。但如果帧数实在太低,则会造成明显的画面撕裂/跳跃。
setTimeout/setInterval在动画中困境
- 计时器处于异步队列中,会等待主线程执行完毕后再执行,因此实际执行时间一般要比设定时间晚一些。
- 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同。
一般为计时器设置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);