requestAnimationFrame
requestAnimationFrame是什么
- 参数是一个回调函数,该回调函数会在浏览器下一次重绘之前执行。
- 回调函数执行次数通常与浏览器屏幕刷新次数相匹配,目前一般是1s刷新60次。
- 当requestAnimationFrame() 运行在后台标签页或者隐藏的 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。比如浏览器tab切换的时候,会停止刷新。
- 调用会执行一次。如果不断更新下一帧动画,那么回调函数自身必须再次调用 window.requestAnimationFrame()
为什么要引入reuestAnimationFrame
- 之前进行定时,或者间隔操作,会使用setTimeout和setIntervel,但是这两个都是内置函数,里面包裹的回调函数终究是等在主函数和微服务运行完之后再执行的,则主函数和微服务的运行事件如果过长,是会堵塞这两个函数运行的。
- requstAnimationFrame是在渲染进程中运行的,js的运行不会堵塞该回调函数的运行,则相对不会有那么长的延迟时间。
语法
window.requestAnimationFrame(callback);
- callback:该回调函数会被传入DOMHighResTimeStamp参数,该参数与performance.now()的返回值相同,它表示requestAnimationFrame() 开始去执行回调函数的时刻。
基本使用
<div class="wrapper">
<div class="btn-wrapper">
<button class="start">开始</button>
<button class="stop">停止</button>
</div>
<div class="box">盒子</div>
</div>
<script>
let timer = null;
let count = 0;
let dom = {
start: document.querySelector(".start"),
stop: document.querySelector(".stop"),
box: document.querySelector(".box"),
};
function step() {
if (count > 200) {
window.cancelAnimationFrame(timer);
return;
}
dom.box.style.transform = `translateX(${count++}px)`;
timer = window.requestAnimationFrame(step);
}
dom.start.addEventListener("click", () => {
timer = window.requestAnimationFrame(step);
});
dom.stop.addEventListener("click", () => {
window.cancelAnimationFrame(timer); // 停止动画的效果
});
</script>
计算每一次运行的时间间隔
- 这里写出例子,来展示20次requestAnimationFrame()的时间间隔,其中,16ms是众数,即1000ms/60次约等于16。
- 【扩展】这里也可以限制多少时间间隔然后再执行对应动作,比如计时等;
//2.计算执行一次的时间
let timer = null;
let count = 0;
let preTimeStamp; //时间戳
function step(timestamp) {
if (preTimeStamp === undefined) {
preTimeStamp = timestamp;
}
let distance = timestamp - preTimeStamp; // 每一次的执行时间间隔。
preTimeStamp = timestamp;
console.log('distance: ', distance); // 众数为16ms。
if (count++ > 20) {
window.cancelAnimationFrame(timer);
return;
}
timer = window.requestAnimationFrame(step);
}
timer = window.requestAnimationFrame(step);