首頁  >  文章  >  web前端  >  HTML5優化Web動畫—requestAnimationFrame

HTML5優化Web動畫—requestAnimationFrame

黄舟
黄舟原創
2017-02-27 15:22:201866瀏覽


在頁面中實作動畫,我們有很多選擇
可以使用CSS3的transition
CSS3中的animation配合keyframes規則
SVG中也可以使用SMIL- animation
最原始的方法就是我們利用JavaScript的setTimeout/setInterval來實作動畫
不過現在我們又多了一個方法
requestAnimationFrame

優點

#requestAnimationFrame的原理與使用方法與setTimeout/setInterval類似
它是以遞歸的形式來實現動畫
既然它是專門用來作Web動畫的,它就一定有它自己的優勢


#使用setTimeout/setInterval製作動畫有以下缺點

  • 無法保證ms的準確性(JavaScript單線程,可能會造成阻塞)

  • 沒有最佳化呼叫動畫的循環機制

  • 沒有考慮到繪製動畫的最佳時機(只是簡單的按一定時間呼叫循環)

相較之下,requestAnimationFrame有以下優點

  • 動畫更加流暢,經由瀏覽器最佳化(頁面刷新前執行一次)

  • 視窗未啟動時,動畫暫停,有效節省CPU開銷

  • 省電,對行動端友善

使用

requestAnimationFrame和setTimeout/setInterval一樣
都是window上的方法
所以我們可以直接使用
requestAnimationFrame()
參數是一個回呼函數,在函數內部我們需要改變元素樣式

#手動執行回呼
同樣回傳一個句柄
傳入cancelAnimationFrame可以取消它

看一個例子

現在我們要讓頁面中的一個元素變寬

<p id="demo"></p>
#demo {    width: 0;    height: 100px;    background-color: orange;}

先來看看setInterval的實作

var demo = document.getElementById(&#39;demo&#39;);
var len = 0;var timerFunc = function(){    len += 5;    if(len <= 200){
        demo.style.width = len + &#39;px&#39;;     
    }else{
        clearInterval(timer);
    }
}var timer = setInterval(timerFunc, 20);

requestAnimationFrame實作的動畫

var demo = document.getElementById(&#39;demo&#39;);var len = 0;
var timerFunc = function(){    len += 5;    if(len <= 200){
        demo.style.width = len + &#39;px&#39;;
        requestAnimationFrame(timerFunc); /*执行回调*/
    }else{
        cancelAnimationFrame(timer); 
    }
}var timer = requestAnimationFrame(timerFunc);

可以發現我們requestAnimationFrame展現的動畫非常的流暢

#相容


既然是比較新的東西,難免就會存在各瀏覽器的兼容性問題

不過現在的瀏覽器已經支援的很好了

我們可以為它寫個polyfill

window.requestAnimationFrame = (function(){  
return  window.requestAnimationFrame       ||          
window.webkitRequestAnimationFrame ||          
window.mozRequestAnimationFrame    ||          
function(callback){            
window.setTimeout(callback, 1000 / 60);
          };
})();
window.requestAnimationFrame = (function(){  
return  window.cancelAnimationFrame       ||          
window.webkitCancelAnimationFrame ||          
window.mozCancelAnimationFrame    ||          
function(ID){            
window.clearTimeout(ID);
          };
})();

如果這個瀏覽器真的什麼都沒有

那麼它只能退化(fallback)使用setTimeout和clearTimeout了


#上面只是一個簡單的polyfill
不過大神寫了更好的

還可以把各瀏覽器前綴進行統一

(function() {
    var lastTime = 0;
    var vendors = [&#39;ms&#39;, &#39;moz&#39;, &#39;webkit&#39;, &#39;o&#39;];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + &#39;RequestAnimationFrame&#39;];
        window.cancelAnimationFrame = window[vendors[x] + &#39;CancelAnimationFrame&#39;] || window[vendors[x] + &#39;CancelRequestAnimationFrame&#39;];
    }
    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);
    };}());

後來又有了更新
相關js可以戳這裡

github原址

if (!Date.now)    
Date.now = function() { return new Date().getTime(); };

(function() {    &#39;use strict&#39;;    
var vendors = [&#39;webkit&#39;, &#39;moz&#39;];    
for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {        
var vp = vendors[i];
        window.requestAnimationFrame = window[vp+&#39;RequestAnimationFrame&#39;];
        window.cancelAnimationFrame = (window[vp+&#39;CancelAnimationFrame&#39;]
                                   || window[vp+&#39;CancelRequestAnimationFrame&#39;]);
    }    if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
        || !window.requestAnimationFrame || !window.cancelAnimationFrame) {        
        var lastTime = 0;
        window.requestAnimationFrame = function(callback) {
            var now = Date.now();            
            var nextTime = Math.max(lastTime + 16, now);            
            return setTimeout(function() { callback(lastTime = nextTime); },
                              nextTime - now);
        };
        window.cancelAnimationFrame = clearTimeout;
    }
}());

有興趣的同學可以研究研究


 以上就是HTML5優化Web動畫—requestAnimationFrame的內容,更多相關內容請關注PHP中文網(www. php.cn)!


####
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn