亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

使用requestAnimationFrame實現(xiàn)js動畫性能好

 更新時間:2015年08月06日 10:12:10   作者:無雙  
requestAnimationFrame優(yōu)于setTimeout/setInterval的地方在于它是由瀏覽器專門為動畫提供的API,在運行時瀏覽器會自動優(yōu)化方法的調(diào)用,并且如果頁面不是激活狀態(tài)下的話,動畫會自動暫停,有效節(jié)省了CPU開銷,這篇文章給大家詳細(xì)介紹使用requestAnimationFrame實現(xiàn)js動畫

使用requestAnimationFrame實現(xiàn)js動畫性能好。先給大家簡單介紹下requestAnimationFrame比起setTimeout、setInterval有哪些優(yōu)勢?

示例一:

requestAnimationFrame 比起 setTimeout、setInterval的優(yōu)勢主要有兩點:
1、requestAnimationFrame 會把每一幀中的所有DOM操作集中起來,在一次重繪或回流中就完成,并且重繪或回流的時間間隔緊緊跟隨瀏覽器的刷新頻率,一般來說,這個頻率為每秒60幀。
2、在隱藏或不可見的元素中,requestAnimationFrame將不會進(jìn)行重繪或回流,這當(dāng)然就意味著更少的的cpu,gpu和內(nèi)存使用量。

像setTimeout、setInterval一樣,requestAnimationFrame是一個全局函數(shù)。調(diào)用requestAnimationFrame后,它會要求瀏覽器根據(jù)自己的頻率進(jìn)行一次重繪,它接收一個回調(diào)函數(shù)作為參數(shù),在即將開始的瀏覽器重繪時,會調(diào)用這個函數(shù),并會給這個函數(shù)傳入調(diào)用回調(diào)函數(shù)時的時間作為參數(shù)。由于requestAnimationFrame的功效只是一次性的,所以若想達(dá)到動畫效果,則必須連續(xù)不斷的調(diào)用requestAnimationFrame,就像我們使用setTimeout來實現(xiàn)動畫所做的那樣。requestAnimationFrame函數(shù)會返回一個資源標(biāo)識符,可以把它作為參數(shù)傳入cancelAnimationFrame函數(shù)來取消requestAnimationFrame的回調(diào)。怎么樣,是不是也跟setTimeout的clearTimeout很相似啊。
所以,可以這么說,requestAnimationFrame就是一個性能優(yōu)化版、專為動畫量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回調(diào)函數(shù)運行的時間,而是跟著瀏覽器內(nèi)建的刷新頻率來執(zhí)行回調(diào),這當(dāng)然就能達(dá)到瀏覽器所能實現(xiàn)動畫的最佳效果了。
目前,各個支持requestAnimationFrame的瀏覽器有些還是自己的私有實現(xiàn),所以必須加前綴,對于不支持requestAnimationFrame的瀏覽器,我們只能使用setTimeout,因為兩者的使用方式幾近相同,所以這兩者的兼容并不難。對于支持requestAnimationFrame的瀏覽器,我們使用requestAnimationFrame,而不支持的我們優(yōu)雅降級使用傳統(tǒng)的setTimeout。把它們封裝一下,就能得到一個統(tǒng)一兼容各大瀏覽器的API了。
代碼可以到這里來查看:https://gist.github.com/chaping/88813f56e75b0fd43f8c

var lastTime = 0;
var prefixes = 'webkit moz ms o'.split(' '); //各瀏覽器前綴
var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame;
var prefix;
//通過遍歷各瀏覽器前綴,來得到requestAnimationFrame和cancelAnimationFrame在當(dāng)前瀏覽器的實現(xiàn)形式
for( var i = 0; i < prefixes.length; i++ ) {
 if ( requestAnimationFrame && cancelAnimationFrame ) {
 break;
 }
 prefix = prefixes[i];
 requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];
 cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] || window[ prefix + 'CancelRequestAnimationFrame' ];
}
//如果當(dāng)前瀏覽器不支持requestAnimationFrame和cancelAnimationFrame,則會退到setTimeout
if ( !requestAnimationFrame || !cancelAnimationFrame ) {
 requestAnimationFrame = function( callback, element ) {
 var currTime = new Date().getTime();
 //為了使setTimteout的盡可能的接近每秒60幀的效果
 var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ); 
 var id = window.setTimeout( function() {
 callback( currTime + timeToCall );
 }, timeToCall );
 lastTime = currTime + timeToCall;
 return id;
 };
 cancelAnimationFrame = function( id ) {
 window.clearTimeout( id );
 };
}
//得到兼容各瀏覽器的API
window.requestAnimationFrame = requestAnimationFrame; 
window.cancelAnimationFrame = cancelAnimationFrame;

這樣子我們就能在所有瀏覽器上使用requestAnimationFrame和cancelAnimationFrame了。
下面舉個簡單的例子來說明怎么運用requestAnimationFrame進(jìn)行動畫,下面的代碼會將id為demo的div以動畫的形式向右移動到300px

<div id="demo" style="position:absolute; width:100px; height:100px; background:#ccc; left:0; top:0;"></div>
<script>
var demo = document.getElementById('demo');
function rander(){
 demo.style.left = parseInt(demo.style.left) + 1 + 'px'; //每一幀向右移動1px
}
requestAnimationFrame(function(){
 rander();
 //當(dāng)超過300px后才停止
 if(parseInt(demo.style.left)<=300) requestAnimationFrame(arguments.callee);
});
</script>


示例二:

一直以來,JavaScript的動畫都是通過定時器和間隔來實現(xiàn)的。雖然使用CSS transitions 和 animations使Web開發(fā)實現(xiàn)動畫更加方便,但多年來以JavaScript為基礎(chǔ)來實現(xiàn)動畫卻很少有所改變。直到Firefox 4的發(fā)布,才帶來了第一種對JavaScript動畫的改善的方法。但要充分認(rèn)識改善,這有利于幫助我們了解web動畫是如何演變改進(jìn)的。
定時器Timer
用于創(chuàng)建動畫的第一個模式是使用鏈?zhǔn)絪etTimeout()調(diào)用。在Netscape 3′s hayday的很長一段時期,開發(fā)者都記得一種在網(wǎng)絡(luò)上隨處可見的固定式最新行情狀態(tài)欄,通常它類似于這樣:

(function(){ 
 var msg = "新的廣告", 
 len = 25, 
 pos = 0, 
 padding = msg.replace(/./g, " ").substr(0,len), 
 finalMsg = padding + msg; 
 function updateText(){ 
 var curMsg = finalMsg.substr(pos++, len); 
 window.status = curMsg; 
 if (pos == finalMsg.length){ pos = 0; } 
 setTimeout(updateText, 100); 
 } 
 setTimeout(updateText, 100); 
})(); 

 如果你想在瀏覽器中測試這段代碼,你可以新建一個
標(biāo)簽用來模擬window.status,例如:newsticker example
這種讓人煩惱的web模式,后來遭到對window.status禁用的抵抗,但隨著Explorer 4和Netscape 4的發(fā)布,瀏覽器第一次給開發(fā)者更多對頁面元素的控制權(quán)限,這種技術(shù)再次出現(xiàn)。這樣就出現(xiàn)了使用javascript動態(tài)改變元素大小、位置、顏色等的一種全新動畫模式。例如,下面就是一個將div寬度變化成100%的動畫(類似于進(jìn)度條):

(function(){ 
 function updateProgress(){ 
 var div = document.getElementByIdx_x("status"); 
 div.style.width = (parseInt(div.style.width, 10) + 5) + "%"; 
 if (div.style.width != "100%"){ setTimeout(updateProgress, 100); } 
 } 
 setTimeout(updateProgress, 100); 
})(); 

盡管動畫在頁面上的地方不同,但基本原理卻是一樣的:做出改變,用setTimeout()間隔使頁面更新,然后setTimeout又執(zhí)行下一次變化,這個過程反復(fù)執(zhí)行,直到動畫完成(見進(jìn)度條動畫),早期的狀態(tài)欄動畫是相同的技術(shù),只是動畫不一樣而已。
間隔動畫Intervals
隨著成功將動畫引入web,新的探索開始了。一個動畫已經(jīng)無法滿足了,現(xiàn)在需要多個動畫。首次嘗試為每個動畫創(chuàng)建多個動畫循環(huán),在早期的瀏覽器中使用setTimeout()來創(chuàng)建多個動畫是有點復(fù)雜的,所以開發(fā)商開始使用setInterval()一創(chuàng)建單一的動畫循環(huán),來管理頁面上所有的動畫,一個使用wetInterval()的基本動畫像這樣:

(function(){ 
 function updateAnimations(){ 
 updateText(); 
 updateProgress(); 
 } 
 setInterval(updateAnimations, 100); 
})();

創(chuàng)建一個小動畫庫,updateAnimations()方法將每一個動畫(同時看到一個新聞股票和進(jìn)度條在一起運行)循環(huán)執(zhí)行并進(jìn)行適當(dāng)?shù)母淖?。如果沒有動畫需要更新,該方法可以退出而不做任何事情,甚至停止動畫循環(huán),直到有更多的動畫更新做好準(zhǔn)備。
動畫問題比較棘手的問題是延遲應(yīng)該為多少。間隔一方面必須足夠短,從而使不同的動畫都能流暢的進(jìn)行,別一方面還要足夠長,使得瀏覽器可以完成渲染。大多數(shù)瀏覽器的刷新頻率為60HZ,即每秒60次刷新,大多數(shù)瀏覽器的刷新頻率都不會比這個更頻繁,因為他們知道,最終用戶是得不到更好的體驗的。
鑒于此,為流暢動畫的最佳時間間隔為1000毫秒/ 60,約17ms。在這個頻率你會看到流暢的動畫,那是因為你最大的接近了瀏覽器能達(dá)到的頻率。跟以前的動畫相比,你會發(fā)現(xiàn)17ms間隔的動畫更加平滑,也更快(因為動畫更新更頻繁,沒有做其他任何修改的情況下),多個動畫可能需要節(jié)流,以免17ms的動畫完成得太快。
問題
即使使用setInterval()為基礎(chǔ)的動畫循環(huán)比多套使用setTimeout()的動畫循環(huán)高效,這里還是存在問題。無論是setInterval()還是setTimeout()都無法達(dá)到精確,這個延遲即你指定的第二個參數(shù)僅僅表示何時代碼會添加到瀏覽器的可能被執(zhí)行的UI線程隊列中。如果隊列中有其他工作在此之前,那代碼將會等到他完成才會執(zhí)行。簡而言之,毫秒級的延遲不是表示何時代碼會執(zhí)行,而是表示何時代碼會添加進(jìn)隊列。如果UI線程處于繁忙狀態(tài)或在處理用戶動作,那么代碼將不會被馬上執(zhí)行。
平滑動畫的關(guān)鍵是理解下一幀何時被執(zhí)行,直到現(xiàn)在都沒有一個方法來保證下一幀將會在瀏覽器中被繪制。隨著的日益流行和新的基于瀏覽器的游戲的出現(xiàn),開發(fā)商對setInterval()和setTimeout()的不精準(zhǔn)越來越感到失望。
瀏覽器的計時器分辨率加劇了這個問題,計時器對毫秒不精準(zhǔn),這里有一些常見的計時器分辨率:
Internet Explorer 8 and earlier 15.625ms
Internet Explorer 9 and later 4ms.
Firefox and Safari ~10ms.
Chrome has a timer 4ms.

IE在版本9之前的的分辨率為15.625,所以0~15之間的任意值可能是0或15,但沒有分別。IE9的計時器分辨率改進(jìn)為4ms,但涉及到動畫時也是不具體的,chrome的計時器分辨率為4ms,firefox 和 safari的為10ms。因此即使你把間隔設(shè)定為最佳的顯示效果,你也僅僅是得到這個近似值。
mozRequestAnimationFrame
Mozilla 的 Robert O'Callahan 在思考這個問題,并想出了一個獨特的方案。他指出CSS transitions 和 animations的優(yōu)勢在于瀏覽器知道哪些動畫將會發(fā)生,所以得到正確的間隔來刷新UI。而javascript動畫,瀏覽器不知道動畫正在發(fā)生。他的解決方案是創(chuàng)建一個mozRequestAnimationFrame()方法來告訴瀏覽器哪些javascript代碼正在執(zhí)行,這使得瀏覽在執(zhí)行一些代碼后得到優(yōu)化。
mozRequestAnimationFrame()方法接受一個參數(shù),是一個屏幕重繪前被調(diào)用的函數(shù)。這個函數(shù)用來對生成下合適的dom樣式的改變,這些改變用在下一次重繪中。你可以像調(diào)用setTimeout()一樣的方式鏈?zhǔn)秸{(diào)用mozRequestAnimationFrame(),例如:

function updateProgress(){ 
 var div = document.getElementByIdx_x("status"); 
 div.style.width = (parseInt(div.style.width, 10) + 5) + "%"; 
 if (div.style.left != "100%"){ 
 mozRequestAnimationFrame(updateProgress); 
 } 
} 


mozRequestAnimationFrame(updateProgress); 
由于mozRequestAnimationFrame()只運行給定的函數(shù)一次,你需要在下一次UI動畫的時候再次調(diào)用它。你也需要相同的方法來管理何時停止調(diào)用。很酷,是非常流暢的動畫增強的實例。
因此,mozRequestAnimationFrame()解決了瀏覽器不知道Javascript動畫正在執(zhí)行和不知道多少才是合適的間隔的問題,但對于不知道何時你的代碼才被真正執(zhí)行,也是由這個方案來解決的。
傳遞給mozRequestAnimationFrame()的函數(shù)實際是一個下一次重繪何時發(fā)生的的時間碼(以毫秒為單位自1970年1月1日計算)。這是很重要的一點:mozRequestAnimationFrame()實際上列表出將要重繪的點并可以告訴你他們所處的時間。這樣你就能夠決定怎樣更好的來調(diào)整你的動畫。
為了得到上次重繪過去的時間,你可以查詢mozAnimationStartTime,其中包含了過去重繪的時間代碼。減去傳遞回調(diào)時的這個值可以計算出下一次重繪到屏幕時所用的時間。使用這些值的典型模式如下:

function draw(timestamp){ 
 //calculate difference since last repaint 
 var diff = timestamp - startTime; 
 //use diff to determine correct next step 
 //reset startTime to this repaint 
 startTime = timestamp; 
 //draw again 
 mozRequestAnimationFrame(draw); 
} 
var startTime = mozAnimationStartTime; 
mozRequestAnimationFrame(draw); 

關(guān)鍵是第一次不是通過callback調(diào)用時,mozAnimationStartTime是到mozRequestAnimationFrame()經(jīng)過的時間。如果是在回調(diào)函數(shù)中,mozAnimationStartTime是通過參數(shù)傳遞進(jìn)來的時間代碼平均值。
webkitRequestAnimationFrame
在很多人熱忠于chrome時,隨即創(chuàng)建了webkitRequestAnimationFrame()方法。這個版本與firefox的版本在兩方面有著細(xì)微的差別。一方面,它不通過回調(diào)函數(shù)傳遞時間代碼,你將無法知道下次重繪何時發(fā)生,另一方面,它添加了第二個可選參數(shù)來確定哪一個DOM元素發(fā)生改變。因此,如果你知道重繪發(fā)生在頁面哪個部分的元素內(nèi),你可以限制重繪發(fā)生的區(qū)域。
應(yīng)該不會感到驚訝,有沒有相應(yīng)的mozAnimationStartTime,因為如果沒有下一個重繪的時間信息不是很有益。有,只是webkitCancelAnimationFrame()取消了之前計劃的重繪。
如果你不需要精確的時間差異,你可以用下面的方式來創(chuàng)建一個用于Firefox4和chrome10+的動畫:

function draw(timestamp){ 
 //calculate difference since last repaint 
 var drawStart = (timestamp || Date.now()), 
 diff = drawStart - startTime; 
 //use diff to determine correct next step 
 //reset startTime to this repaint 
 startTime = drawStart; 
 //draw again 
 requestAnimationFrame(draw); 
} 
var requestAnimationFrame = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame, 
startTime = window.mozAnimationStartTime || Date.now(); 
requestAnimationFrame(draw); 

這種模式使用可用的方法來創(chuàng)建以花費多少時間為理念的循環(huán)動畫。Firefox使用時間代碼信息是有用的,而Chrome默認(rèn)為欠精準(zhǔn)的時間對象。當(dāng)用這種模式的時候,時間的差異給你一種多少時間過去了的想法,但不會告訴你Chrome的下一次重繪出現(xiàn)在何時。不過這比只有多少時間過去了的模糊概念要好些。
總結(jié)
mozRequestAnimationFrame()方法的介紹為推動Javascript 動畫及web的歷史發(fā)展有著非常重要的作用。如前所述,JavaScript動畫的態(tài)幾乎和JavaScript的初期一樣。隨著瀏覽器逐漸推出CSS transitions 和 animations,很高興看到基于JavaScript的動畫的關(guān)注,因為這些在基于的游戲領(lǐng)域?qū)⒆兊酶匾透cCUP聯(lián)系緊密。知道Javascript何時嘗試動畫,允許瀏覽器做更多的優(yōu)化處理,包括在tab處于后臺或移動設(shè)備電量過低時停止進(jìn)程。
該requestAnimationFrame()API現(xiàn)在正由W3C起草一個新議案,并正由Mozilla和Google努力使之成為Web大舞臺的一部分。很高興能看到這兩大集團(tuán)這么迅速的兼容(可能不完全)實現(xiàn)。
RequestAnimFrame使用
對于一個偵中對DOM的所有操作,只進(jìn)行一次Layout和Paint。
如果發(fā)生動畫的元素被隱藏了,那么就不再去Paint。

window.requestAnimFrame = (function(){ 
 return window.requestAnimationFrame || 
 window.webkitRequestAnimationFrame || 
 window.mozRequestAnimationFrame || 
 window.oRequestAnimationFrame || 
 window.msRequestAnimationFrame || 
 function( callback ){ 
  window.setTimeout(callback, 1000/60); 
 }; 
})(); 
//調(diào)用 
function animationLoop(elem){ 
 requestAnimFrame(animationLoop); 
//logic 
} 
Or
window.requestAnimFrame = (function(w, r) { 
 w['r'+r] = w['r'+r] || w['webkitR'+r] || w['mozR'+r] || w['msR'+r] || w['oR'+r] || function(c){ w.setTimeout(c, 1000 / 60); }; 
 return w['r'+r]; 
})(window, 'equestAnimationFrame'); 

以上通過兩段代碼示例詳解說明了使用requestAnimationFrame實現(xiàn)js動畫性能好,希望大家喜歡。

相關(guān)文章

  • window.location 對象所包含的屬性

    window.location 對象所包含的屬性

    這篇文章主要介紹了window.location 對象所包含的屬性,這些熟悉都是工作中經(jīng)常會用到的,很實用,需要的朋友可以參考下
    2014-10-10
  • Bootstrap實現(xiàn)基于carousel.js框架的輪播圖效果

    Bootstrap實現(xiàn)基于carousel.js框架的輪播圖效果

    這篇文章主要為大家詳細(xì)介紹了Bootstrap實現(xiàn)基于carousel.js框架的輪播圖效果,無過渡動畫,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • js字符串的各種格式的轉(zhuǎn)換 ToString,F(xiàn)ormat

    js字符串的各種格式的轉(zhuǎn)換 ToString,F(xiàn)ormat

    平時我們經(jīng)常會需要將字符轉(zhuǎn)換為各種不同的格式,例如錢:0元需要轉(zhuǎn)換為0.00顯示;需要轉(zhuǎn)換為16進(jìn)制顯示的數(shù),這樣的例子有很多
    2011-08-08
  • 微信小程序 自定義消息提示框

    微信小程序 自定義消息提示框

    這篇文章主要介紹了微信小程序 自定義消息提示框的相關(guān)資料,wx.showToast(OBJECT)接口調(diào)用,實現(xiàn)改功能,需要的朋友可以參考下
    2017-08-08
  • Flexible.js可伸縮布局實現(xiàn)方法詳解

    Flexible.js可伸縮布局實現(xiàn)方法詳解

    這篇文章主要介紹了Flexible.js可伸縮布局實現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • html5 canvas 詳細(xì)使用教程

    html5 canvas 詳細(xì)使用教程

    本文主要對html5 canvas的使用進(jìn)行了詳細(xì)的介紹。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • apicloud拉起小程序并傳遞參數(shù)的方法示例

    apicloud拉起小程序并傳遞參數(shù)的方法示例

    這篇文章主要介紹了apicloud拉起小程序并傳遞參數(shù)的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • 深入探尋javascript定時器

    深入探尋javascript定時器

    這篇文章主要介紹了深入探尋javascript定時器,十分的詳盡,十分全面,需要的朋友可以參考下
    2015-01-01
  • js動態(tài)為代碼著色顯示行號

    js動態(tài)為代碼著色顯示行號

    使用Javascript插件,在瀏覽器客戶端動態(tài)的為代碼著色,可以顯示行號,具體實現(xiàn)代碼如下,感興趣的朋友可以參考下哈
    2013-05-05
  • Uniapp?實現(xiàn)全民分銷功能原理解析

    Uniapp?實現(xiàn)全民分銷功能原理解析

    這篇文章主要介紹了Uniapp?實現(xiàn)全民分銷功能,本篇文章主要介紹全民分銷功能實現(xiàn)原理,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評論