你可能不了解的动画神器之requestAnimationFrame及其兼容写法

2018-03-01 11:01:15来源:segmentfault作者:myway人点击

分享
介绍此篇文章翻译自paul_irish( 就职于Google Chrome团队工程师)
文中提到对requestAnimationFrame的polyfill非常不错,可以直接拿来用
原文链接:requestAnimationFrame for Smart Animating
什么是requestAnimationFrame?

你可能用过定时器实现动画(通过每隔一段时间去改变元素)。浏览器给我们带来了个好消息“为什么不提供一个API给开发者,来使一些事情更高效呢”。requestAnimationFrame就是为动画而生的API,用于改变dom样式、canvas或WebGL。


我为什么要使用它?

浏览器能够将并发动画优化为单个事件流和重绘周期中,从而更流畅。例如同时进行的如下任务:基于js的动画、css动画、SVG SMIL。而且,当正在执行动画的标签页不可见时,浏览器并不会一直运行它,这就意味着更少的CPU、 GPU和内存的使用,从而延长电池寿命。


天啦噜,我可以吹嘘自己的网站对电池更友好?

是的大兄弟Totes McGoats(此人跟作者是啥关系~)


我应该如何使用它?

下面这段是一个简单的requestAnimationFrame兼容写法,当浏览器不支持时回退到setTimeout的实现方式:


// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
returnwindow.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
// usage:
// instead of setInterval(render, 16) ....(function animloop(){
requestAnimFrame(animloop);
render();
})();
// place the rAF *before* the render() to assure as close to
// 60fps with the setTimeout fallback.
更加健壮的polyfill

以下代码是Opera工程师Erik Möller所写更加健壮的polyfill。你可以阅读下,尤其是在处理4-16ms的延迟时间这段代码,从而使帧率更接近60fps。你会喜欢上它的,请注意他使用的标准方法名。我同时也修正了cancel方法名称(WebKit内核的浏览器已更改过)。


(function() {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
来看看它的效果

http://jsfiddle.net/XQpzU/435...


requestAnimationFrame API
window.requestAnimationFrame(function(/* time */ time){
// time ~= +new Date // the unix time
});

该回调函数将当前时间作为参数传递,也正是你说需要的。


(此文写于2011年,下面介绍了不同浏览器实现上的差异)
Is it ready?
Right now, the Webkit implementation (available in Nightly Safari and Chrome Dev Channel) and the Mozilla one (available in FF4) differ slightly. Mozilla’s has a bug which caps potential framerates at about 30fps.Actually, “It’s currently capped at 1000/(16 + N) fps, where N is the number of ms it takes your callback to execute. If your callback takes 1000ms to execute, then it’s capped at under 1fps. If your callback takes 1ms to execute, you get about 60fps.” (thx, Boris) It’ll be fixed though, probably for the next release after FF4 ships. Also Chrome 10 doesn’t have the time parameter (added in m11), FF currently ignores the element argument.

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台