[翻译]使用requestAnimationFrame实现炫目的动画

写缓动函数用到requestAnimationFrame函数,之前了解过一些,但总觉得又不是很了解,所以翻译一篇老外的文章,以便学习分享。
 

requestAnimationFrame是什么?
以前我们做动画需要一个定时器,每间隔多少毫秒就做出一些改变。现在有个好消息:浏览器厂商已经决定提供一个专门做动画的方法,即requestAnimationFrame(),而且基于浏览器的层面也能更好的进行优化。但是呢,这只是一个做动画的基础API,即不基于DOM元素的style变化,也不基于canvas,或者WebGL。所以,具体的动画细节需要我们自己写。
 

我们为什么要用它?

对于同时进行的n个动画,浏览器能够进行优化,把原本需要N次reflow和repaint优化成1次,这样就实现了高质量的动画。举个例子,现在有基于JS的动画,还有基于CSS的transitions,或者SVG SMIL. Plus,如果浏览器的某个tab正在运行这样一个动画,然后你切到另一个tab,或者干脆最小化,总之就是你看不见它了,这时浏览器就会停止动画。这将意味着更少的CPU,GPU和更少的内存消耗,这样电池的使用寿命就大大延长了。
 

如何使用它?

// shim layer with setTimeout fallback
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function(/* function */ callback, /* DOMElement */ element){
                window.setTimeout(callback, 1000 / 60);
              };
    })();
 
    // usage: 
    // instead of setInterval(render, 16) ....
 
    (function animloop(){
      render();
      requestAnimFrame(animloop, element);
    })();

注意:这里我使用了“requestAnimFrame”,因为规范仍在不断变化中,我并不想任由规范摆布。
 

requestAnimationFrame API

window.requestAnimationFrame(function(/* time */ time){
	// time ~= +new Date // the unix time
}, /* optional bounding elem */ elem);


先给出Chrome和Firefox的版本

window.mozRequestAnimationFrame([callback]);             // Firefox
window.webkitRequestAnimationFrame(callback[, element]); // Chrome


参数:

callback:(FF可选,Chrome必选)

  下次repaint调用的函数,函数的第一个参数是当前时间

element:(FF无)

  意译一下吧:其实就是画布了,而那个‘画’,是动画。(the element that visually bounds the entire animation)。对canvas和WebGL来说,它就是<canvas>元素,对于DOM节点来说,你可以不管它,如果你想稍微进行一下优化,也可以传个参数进来。
 

它到底靠不靠谱啊?

现在,Webkit实现(Nightly Safari 和 Chrome Dev Channel 可用)和Mozilla实现(FF4可用)有一些的差异,Mozilla的实现有一个Bug。事实上,FF动画的帧数是这么算的:1000/(16 + N) fps,其中N是callback的执行时间,单位为毫秒。如果你的callback执行时间为1000ms,那么它最高的帧数也就只有1fps。如果你的callback执行时间为1ms,那么帧数差不多就是60fps。这个bug肯定会被修复,也许就是FF4的下一个版本吧。Chrome10没有time参数(added in m11.弱弱的问下,m11是什么?),FF目前没有element参数。
 
我看了下火狐的那个bug,大概就是说:

FF的mozRequestAnimationFrame()永远不可能达到60fps,即使你的callback执行时间小于1000/60毫秒。举个例子:

function callback(time) {
	window.mozRequestAnimationFrame(callback);
	doWork();
}

如果doWork()耗时1000/60毫秒,那么帧数大约是30fps,而同样的动画如果使用setTimeout(callback, 16),帧速则是60fps。似乎callback总是在callback执行完毕后的大约16ms再次开始执行,而不是在callback开始执行后的16ms再次开始执行,如果是后者,且计算又够快的话,就能产生60fps的帧数。


如果你是规范控,传送门在此



来源:

requestAnimationFrame for smart animating

MDN

posted @ 2011-09-30 16:42  越己  阅读(4736)  评论(13编辑  收藏  举报