web动画新选择:requestAnimationFrame

作者:If you’ve never written code to animate inside the browser, you can stop reading :)

requestAnimationFrame是什么?

在浏览器中,我们通常使用一个定时器(setInterval & setTimeout)来循环每隔几毫秒移动目标物体一次,来让它动起来。

如今有一个好消息,浏览器开发商们决定:“嗨,为什么我们不在浏览器里提供这样一个API呢,这样一来我们可以为用户优化他们的动画。”所以,这个requestAnimationFrame()函数就是针对动画效果的API,你可以把它用在DOM上的风格变化或canvaswebGL中。

为什么我们要用它?

  • 浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。比如,通过requestAnimationFrame(),JS动画能够和CSS动画/变换或SVG SMIL动画同步发生。
  • 另外,如果在一个浏览器标签页里运行一个动画,当这个标签页不可见时,浏览器会暂停它,这会减少CPU,内存的压力,节省电池电量。

和setTimeout、setInterval的区别

  • setInterval、setTimeout是开发者主动要求浏览器去绘制,但是由于种种问题,浏览器可能会漏掉部分命令
  • requestAnimationFrame 就是浏览器什么要开始绘制了浏览器自己知道,通过requestAnimationFrame 告诉开发者,这样就不会出现重复绘制丢失的问题了

requestAnimationFrame的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//向下兼容,使用setTimeout
window.requestAnimFrame = (function(){
return window.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.

Opera浏览器的技术师Erik Möller 把这个函数进行了封装,使得它能更好的兼容各种浏览器。但基本上他的代码就是判断使用4ms还是16ms的延迟,来最佳匹配60fps。
下面就是这段代码,你可以使用它,但请注意,这段代码里使用的是标准函数,我给它加上了cancel*方法和兼容各种浏览器引擎前缀。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
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);
};
}());

或者访问作者在Gist上的源码

让我们看看效果

The requestAnimationFrame API

1
2
3
4
5
window.requestAnimationFrame(function(/* time */ time){
// time ~= +new Date // the unix time
});

//回调函数里的第一个参数可以传入时间。

关于兼容

使用can i use查看

转自:http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2019 FE blog All Rights Reserved.

访客数 : | 访问量 :