web動畫的幾種實現(xiàn)方法
- css3動畫
- setTimeout/setInterval實現(xiàn)
- requestAnimationFrame實現(xiàn)
requestAnimationFrame是什么宾肺?
在瀏覽器動畫程序中溯饵,我們通常使用一個定時器來循環(huán)每隔幾毫秒移動目標(biāo)物體一次,來讓它動起來锨用。如今有一個好消息丰刊,瀏覽器開發(fā)商們決定:“嗨,為什么我們不在瀏覽器里提供這樣一個API呢增拥,這樣一來我們可以為用戶優(yōu)化他們的動畫啄巧⊙捌纾”所以,這個requestAnimationFrame()
函數(shù)就是針對動畫效果的API秩仆,你可以把它用在DOM上的風(fēng)格變化或畫布動畫或WebGL中码泛。
使用requestAnimationFrame有什么好處?
瀏覽器可以優(yōu)化并行的動畫動作澄耍,更合理的重新排列動作序列噪珊,并把能夠合并的動作放在一個渲染周期內(nèi)完成,從而呈現(xiàn)出更流暢的動畫效果齐莲。比如痢站,通過requestAnimationFrame()
,JS動畫能夠和CSS動畫/變換或SVG SMIL動畫同步發(fā)生铅搓。另外瑟押,如果在一個瀏覽器標(biāo)簽頁里運行一個動畫,當(dāng)這個標(biāo)簽頁不可見時星掰,瀏覽器會暫停它多望,這會減少CPU,內(nèi)存的壓力氢烘,節(jié)省電池電量怀偷。
requestAnimationFrame的用法
// shim layer with setTimeout fallback
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.
requestAnimationFrame的API完善
下面是由Paul Irish及其他貢獻(xiàn)者放在GitHub Gist上的代碼片段,用于在瀏覽器不支持requestAnimationFrame情況下的回退播玖,回退到使用setTmeout的情況椎工。當(dāng)然,如果你確定代碼是工作在現(xiàn)代瀏覽器中蜀踏,下面的代碼是不必的维蒙。
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik M?ller. fixes from Paul Irish and Tino Zijdel
// MIT license
(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);
};
}());
各種瀏覽器對requestAnimationFrame的支持情況
谷歌瀏覽器,火狐瀏覽器果覆,IE10+都實現(xiàn)了這個函數(shù)颅痊,即使你的瀏覽器很古老,上面的對requestAnimationFrame封裝也能讓這個方法在IE8/9上不出錯局待。
<iframe>
<div id="test" style="width:1px;height:17px;background:#0f0;">0%</div>
<input type="button" value="Run" id="run"/>
<script type='text/javascript'>console.log(1);window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;var start = null;var ele = document.getElementById('test');var progress = 0;function step(timestamp){progress += 1;ele.style.width = progress + "%"; ele.innerHTML=progress + "%"; if (progress < 100) { requestAnimationFrame(step); } }requestAnimationFrame(step);document.getElementById("run").addEventListener("click", function() { ele.style.width = "1px"; progress = 0; requestAnimationFrame(step); }, false); </script>
</iframe>
一個應(yīng)用例子
http://jsfiddle.net/XQpzU/4358/?utm_source=website&utm_medium=embed&utm_campaign=XQpzU