在刚开始接触前端的时候,可能很多人对requestAnimationFrame这个不是很了解,感觉有了setTimeout,setInterval,这requestAnimationFrame是不是有点多余了,其实不是的,老铁们,真不是您想的那样,这requestAnimationFrame可是有人家自己的绝活的,接下来将登场的就是requestAnimationFrame,他是我们这篇文章的主角......
目前市面上的显示器有CRT(Cathode Ray Tube)显示器和LCD(Liquid Crystal Display)显示两种,CRT是一种使用阴极射线管的显示器,LCD则是我们经常听到的液晶显示器。
CRT显示器屏幕上的图形图像是由一个个阴电子束击打发光的荧光点组成,电子束击打后发光的时间很短,电子束会不停地击打荧光点。电子束每秒击打荧光点的次数就是屏幕绘制频率
LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置TFT(薄膜晶体管),上基板玻璃上设置彩色滤光片,通过TFT上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。不管是CRT还是LCD都会高频率地更新屏幕上的图像,即使没有任何动画的情况,我们感觉不到是因为有视觉停留效应,如果屏幕的绘制频率是每秒60次,我们通常会说帧率是每秒60帧 (1000/60)。如果是一秒钟一帧,我们就会感觉非常卡顿。
显示器上每绘制完一帧都会调用requestAnimationFrame里的会调函数,而setTimeout函数的执行时间并不是确定的,setTimeout里的任务被推到了异步队列里,只有当主线程上的任务执行完毕以后,才会去检测该队列里的任务是否需要开始执行,所以setTimeout的实际执行时机一般要比其设定的时间晚一些,再则,也很容易掉帧,我们来看个例子
假设屏幕1秒刷新一次,setTimeout每隔0.8秒执行一次
* 0s 屏幕未绘制 setTimeout 未执行
* 0.8s 屏幕未绘制 setTimeout 执行
* 1s 屏幕绘制 setTimeout未执行
* 1.6s 屏幕未绘制 setTimeout执行
* 2s 屏幕绘制 setTimeout未执行
* 2.4s 屏幕未绘制 setTimeout执行
* 3s 屏幕绘制 setTimeout未执行
* 3.2 屏幕未绘制 setTimeout执行
* 4s屏幕绘制 setTimeout执行
从上面我们可以推看出setTimeout容易掉帧,也容易导致性能问题,而requestAnimationFrame则恰到好处地每次更新渲染,每次执行
下面来看下requestAnimationFrame的简单例子:
来根据浏览器的不同做下兼容处理
var rAF = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) { window.setTimeout(callback, 1000 / 60); };
取消
const rAFCancel = window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
function(callback) {
window.clearTimeout(callback, 1000 / 60);
}