一般我们绘画动画会使用计时器,动画的形成本身就是一帧一帧的画面按照一定的速度展示出来,使用计时器就是为了把渲染出来的图像按照我们能感知到的速度展示出来,例如一个旋转动画,需要把旋转图片拆分成几个旋转90°的动作,使用计时器一步一步旋转以达到用户能看到的旋转效果。
但是这里就会出现一些问题,每台设备的渲染帧频率不会完全相同,动画渲染不一,可能出现不流畅的情况,如果是一些性能较差的低配手机,甚至会失帧的情况。
setTimeout
一般动画编写我们会使用setTimeout这个函数,但是利用seTimeout实现的动画在一些低端机上会出现失帧、卡顿、抖动等现象。 产生有两个原因:
setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。
上面我们提到的一点:每台设备的渲染帧频率不会完全相同,动画渲染不一,刷新频率又受屏幕分辨率和屏幕尺寸的影响,setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间吻合。
setTimeout执行的图像变化并不是马上反应到屏幕,这个变化必须要等到屏幕下次刷新时才会被更新到屏幕上。如果我们定义的时间和屏幕的刷新时间步调不一致,就可能会导致中间某一帧的操作被跨越过去,而直接更新下一帧的图像,从而导致失帧。
requestAnimationFrame
requestAnimationFrame是html5提供的的一个叫请求动画帧的api。这个api是根据系统渲染屏幕时间来调用的,每渲染一次就调用一次,这样就保证了帧数完整地执行并且不会失帧。
function animate() {
left ++
console.log("animation");
if (left <50) {
window.requestAnimationFrame(animate);
}
}
//第一帧渲染
window.requestAnimationFrame(animate);
兼容:
var requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){window.setTimeout(callback,1000/60);};