首页 > 代码库 > requestAnimationFrame简介

requestAnimationFrame简介


# requestAnimationFrame简介

当我们需要实现动画时,最先想到的会是**setTimeout**和**setInterval**这两个函数。css3动画出来后,我们也可以使用css3来实现动画。然而这两种方法都有很大的局限性。

一般情况下,使用**setTimeout**和**setInterval**这两个函数加上一个延迟时间以及每一帧的效果,连贯后看起来就成了动画。然而使用这两个函数做动画有几个问题:

- 延迟时间不精确(具体可参考[js:从setTimeout说时间循环模型][1]);
- 不能和浏览器的刷新频率同步,可能会出现“掉帧”现象;
- 性能较差(如页面最小化之后仍然会运行等);

同样的,虽然css3动画的性能和流畅度要优于前者,但能实现的效果种类太少,且并非所有属性都能参与动画,无法控制动画的全过程……

requestAnimationFrame是专门为实现高性能动画而设计的一个API,其在MDN上的定义如下:

> window.requestAnimationFrame()这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数,以满足开发者操作动画的需求。这个方法接受一个函数为参,该函数会在重绘前调用。

那么,requestAnimationFrame有哪些优势呢?概括起来有一下几点:

- 和浏览器的刷新率同步
requestAnimationFrame会把每一帧中的DOM操作全部集中起来,进行统一重绘,重绘的频率与浏览器的刷新率一致,一般为60帧每秒。而**setTimeout**是独立绘制的,性能明显较差;
- 当页面最小化或隐藏时,requestAnimationFrame将大大降低重绘频率;

可见requestAnimationFrame用来做动画是再适合不过了,然而其兼容性还不够优秀。
![requestAnimationFrame-desktop][2]
![requestAnimationFrame-mobile][3]

虽然PC端上的主流浏览器大部分支持requestAnimationFrame,但在移动端的表现很糟糕。为此,可以编写一个统一兼容各大浏览器的API:
```javascript
window.raf = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.oRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(callback) {
window.setTimeout(callback, 1000 / 60);
};
```
考虑到部分设备的绘制频率不为60fps,对上述代码加强:
```javascript
var lastTime = 0;
var vendors = [‘webkit‘, ‘moz‘, ‘o‘, ‘ms‘];

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 currentTime = new Date().getTime();
var timeToCall = Math.max(0, 16.7 - (currentTime - lastTime));
var id = window.setTimeout(function(){
callback(currentTime + timeToCall);
}, timeToCall);
lastTime = currentTime + timeToCall;
return id;
};
}
if(!window.cancelAnimationFrame){
window.cancelAnimationFrame = function(id){
window.clearTimeout(id);
};
}
```
这样,就可以在绝大部分浏览器中使用requestAnimationFrame来制作动画了。


----------

相关阅读

- [JavaScript Tween算法及缓动效果][4]
- [Understanding Easing (Explaining Penner’s equations)][5]


[1]: http://www.cnblogs.com/Medeor/p/4945687.html
[2]: http://static.nichoo.cn/images/requestAnimationFrame-desktop.png
[3]: http://static.nichoo.cn/images/requestAnimationFrame-mobile.png
[4]: http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html
[5]: http://upshots.org/actionscript/jsas-understanding-easing

requestAnimationFrame简介