之前知道异步有个
requestAnimationFrame
,但一直没去了解,今天有空学了下,记录一波。
参考资料:
为什么需要requestAnimationFrame
传统的
javascript
动画是通过定时器setTimeout
或者setInterval
实现的。
但是定时器动画一直存在两个问题:1. 动画的循时间环间隔不好确定,设置长了动画显得不够平滑流畅,设置短了浏览器的重绘频率会达到瓶颈,推荐的最佳循环间隔是17ms(大多数电脑的显示器刷新频率是60Hz,1000ms/60);2. 定时器第二个时间参数只是指定了多久后将动画任务添加到浏览器的UI线程队列中,如果UI线程处于忙碌状态,那么动画不会立刻执行。为了解决这些问题,H5 中加入了requestAnimationFrame
;
requestAnimationFrame的优势
requestAnimationFrame
会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率- 在隐藏或不可见的元素中,
requestAnimationFrame
将不会进行重绘或回流,这当然就意味着更少的 CPU、GPU 和内存使用量 requestAnimationFrame
是由浏览器专门为动画提供的 API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了 CPU 开销
requestAnimationFrame的使用场景
- 动画:
requestAnimationFrame
本来就是为动画而生的,所以在处理 js 动画不在话下,与定时器的用法非常相似,下面是一个例子,点击元素时开始转动,再次点击转动速速增加。 - 大量数据渲染:在大量数据渲染过程中,比如表格的渲染,如果不进行一些性能策略处理,就会出现 UI 冻结现象,用户体验极差。有个场景,将后台返回的十万条记录插入到表格中,如果一次性在循环中生成 DOM 元素,会导致页面卡顿5s左右。这时候我们就可以用
requestAnimationFrame
进行分步渲染,确定最好的时间间隔,使得页面加载过程中很流畅。
requestAnimationFrame的用法
// 用法
// 效果类似setInterval,但不需要第二个时间参数
// 因为他自身已经做了优化,会自动在浏览器下一次重绘之前调用callback
window.requestAnimationFrame(callback);
// 取消一个requestAnimationFrame
// 也跟setInterval类似,但是这个cancelAnimationFrame的兼容性不太好
const requestID = window.requestAnimationFrame(callback);
window.cancelAnimationFrame(requestID);