requestAnimationFrame,Web中寫動畫的另一種選擇

來源:互聯網
上載者:User

標籤:

HTML5/CSS3時代,我們要在web裡做動畫選擇其實已經很多了:

你可以用CSS3的animattion+keyframes;

你也可以用css3的transition;

你還可以用通過在canvas上作圖來實現動畫,也可以藉助jQuery動畫相關的API方便地實現;

當然最原始的你還可以使用window.setTimout()或者window.setInterval()通過不斷更新元素的狀態位置等來實現動畫,前提是畫面的更新頻率要達到每秒60次才能讓肉眼看到流暢的動畫效果。

現在又多了一種實現動畫的方案,那就是還在草案當中的window.requestAnimationFrame()方法。

初識requestAnimationFrame

來看MDN上對其給出的詮釋:

The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes as an argument a callback to be invoked before the repaint.

window.requestAnimationFrame() 將告知瀏覽器你馬上要開始動畫效果了,後者需要在下次動畫前調用相應方法來更新畫面。這個方法就是傳遞給window.requestAnimationFrame()的回呼函數。

也可這個方法原理其實也就跟setTimeout/setInterval差不多,通過遞迴調用同一方法來不斷更新畫面以達到動起來的效果,但它優於setTimeout/setInterval的地方在於它是由瀏覽器專門為動畫提供的API,在運行時瀏覽器會自動最佳化方法的調用,並且如果頁面不是啟用狀態下的話,動畫會自動暫停,有效節省了CPU開銷。

基本文法

可以直接調用,也可以通過window來調用,接收一個函數作為回調,返回一個ID值,通過把這個ID值傳給window.cancelAnimationFrame()可以取消該次動畫。

requestAnimationFrame(callback)//callback為回呼函數

 

一個簡單的例子

類比一個進度條動畫,初始div寬度為1px,在step函數中將進度加1然後再更新到div寬度上,在進度達到100之前,一直重複這一過程。

為了示範方便加了一個運行按鈕(看不到例子請重新整理)。

<div id="test" style="width:1px;height:17px;background:#0f0;">0%</div><input type="button" value="Run" id="run"/>
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);

 

瀏覽器支援情況

既然還是草案狀態下引入的一個功能,在使用全我們就需要關心一下各瀏覽器對它的支援情況了。就目前來說,主流現代瀏覽器都對它提供了支援,請看:

31+

26+

10+

19+

6+

 

更為具體的瀏覽器安全色性可以在這裡看到。

Polyfill

Polyfill就是墊片,按發明這個詞的人的原話來說,它就是一段這樣的代碼,讓瀏覽器原生地支援我們期望使用的一些API。

就比如這裡的requestAnimationFrame,在看到了上面的瀏覽器支援情況後,你就知道了比上面列出的瀏覽器版本老的就不支援該方法,但為了讓代碼能夠有更好的瀏覽器安全色性在老機器上也能運行不報錯,我們可以寫一些代碼讓瀏覽器在不支援requestAnimationFrame的情況下使用window.setTimeout(),這是一種回退(fallback)到過去的方法。

這樣一來,就可以通俗一點的理解polyfill了,它就是備胎。

下面是由Paul Irish及其他貢獻者放在GitHub Gist上的程式碼片段,用於在瀏覽器不支援requestAnimationFrame情況下的回退,回退到使用setTmeout的情況。當然,如果你確定代碼是工作在現代瀏覽器中,下面的代碼是不必的。

// 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方法時將其指向setTimeout方法。

提到備胎代碼呢,這裡多說一句,在CSS代碼中,我們也經常使用這種回退的技巧,即對同一條CSS規則,編寫多條以不同瀏覽器首碼開頭代碼,或者編寫一條備用樣式。

下面是一個CSS中的備胎代碼的例子:

div {    background: rgb(0, 0, 0); /* fallback */    background: rgba(0, 0, 0, 0.5);}

 

代碼中設定div背景為黑色帶50%的透明度,但IE9-的瀏覽器是不支援rbga格式的顏色的,所以瀏覽器會回退到上一條CSS規則應用rgb顏色。

 

requestAnimationFrame,Web中寫動畫的另一種選擇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.