說說requestAnimationFrame

首先從字面意思來看,就是請求動畫幀(后面用raf代替)底燎。
說起動畫蠢络,css3的transition和animation,js的setTimeout和setInterval效览,jquery的animate()都可以做動畫无切,這幾種方式的性能和效率也有不同。今天聊的這個也可以做動畫丐枉。

是什么

說白了就是做幀動畫用的哆键,所謂的請求動畫幀,是告訴瀏覽器在下一次屏幕刷新的時候瘦锹,別忘了運行raf這個方法籍嘹,這一塊要注意一點:每次屏幕刷新的時候,都會運行raf弯院。也就是raf的運行頻率是根據(jù)屏幕刷新頻率來決定的辱士。

性能怎么樣

首先聊聊setTimeout。
setTimeout 其實就是通過設(shè)置一個間隔時間來不斷的改變圖像的位置听绳,從而達到動畫效果的识补。但我們會發(fā)現(xiàn),利用seTimeout實現(xiàn)的動畫在某些低端機上會出現(xiàn)卡頓辫红、抖動的現(xiàn)象凭涂。 這種現(xiàn)象的產(chǎn)生有兩個原因:

1.setTimeout的執(zhí)行時間并不是確定的。在Javascript中贴妻, setTimeout 任務(wù)被放進了異步隊列中切油,實際上只是指定了把動畫代碼添加到瀏覽器UI線程等待執(zhí)行的時間,如果隊列前面有其他任務(wù)名惩,只有當主線程上的任務(wù)執(zhí)行完以后澎胡,才會去檢查該隊列里的任務(wù)是否需要開始執(zhí)行,因此 setTimeout 的實際執(zhí)行時間一般要比其設(shè)定的時間晚一些娩鹉。
2.刷新頻率受屏幕分辨率和屏幕尺寸的影響攻谁,因此不同設(shè)備的屏幕刷新頻率可能會不同,而 setTimeout只能設(shè)置一個固定的時間間隔弯予,這個時間不一定和屏幕的刷新時間相同戚宦。
以上兩種情況都會導致setTimeout的執(zhí)行步調(diào)和屏幕的刷新步調(diào)不一致,從而引起丟幀現(xiàn)象锈嫩。 那為什么步調(diào)不一致就會引起丟幀呢受楼?

首先要明白垦搬,setTimeout的執(zhí)行只是在內(nèi)存中對圖像屬性進行改變,這個變化必須要等到屏幕下次刷新時才會被更新到屏幕上艳汽。如果兩者的步調(diào)不一致猴贰,就可能會導致中間某一幀的操作被跨越過去,而直接更新下一幀的圖像河狐。假設(shè)屏幕每隔16.7ms刷新一次米绕,而setTimeout每隔10ms設(shè)置圖像向左移動1px, 就會出現(xiàn)如下繪制過程:

第0ms: 屏幕未刷新馋艺,等待中义郑,setTimeout也未執(zhí)行,等待中丈钙;
第10ms: 屏幕未刷新非驮,等待中,setTimeout開始執(zhí)行并設(shè)置圖像屬性left=1px雏赦;
第16.7ms: 屏幕開始刷新劫笙,屏幕上的圖像向左移動了1px, setTimeout 未執(zhí)行星岗,繼續(xù)等待中填大;
第20ms: 屏幕未刷新,等待中俏橘,setTimeout開始執(zhí)行并設(shè)置left=2px;
第30ms: 屏幕未刷新允华,等待中,setTimeout開始執(zhí)行并設(shè)置left=3px;
第33.4ms:屏幕開始刷新寥掐,屏幕上的圖像向左移動了3px靴寂, setTimeout未執(zhí)行,繼續(xù)等待中召耘;

從上面的繪制過程中可以看出百炬,屏幕沒有更新left=2px的那一幀畫面,圖像直接從1px的位置跳到了3px的的位置污它,這就是丟幀現(xiàn)象剖踊,這種現(xiàn)象就會引起動畫卡頓。所以丟幀現(xiàn)象可以說是因為屏幕刷新頻率和代碼執(zhí)行不對稱導致的衫贬。

那如果屏幕刷新頻率和代碼執(zhí)行對稱的話德澈,是不是就不會發(fā)生丟幀現(xiàn)象了?固惯?梆造。raf的誕生就解決了這一點,上文已經(jīng)說了缝呕,raf的執(zhí)行頻率是根據(jù)屏幕刷新頻率來說的澳窑,有圖像的變化就會刷新屏幕,刷新屏幕就會運行raf供常,這樣就解決了丟幀的現(xiàn)象摊聋。

如何用

raf()會接收一個參數(shù),這個參數(shù)是一個函數(shù)栈暇,函數(shù)的作用就是負責改變下一次重繪時dom的樣式麻裁。

var i = 0;
function updateDom(){
  let box = document.getElementById('box');
  i+=10;
  box.style.width = 300 + i +'px';
  if(i<500){
      requestAnimationFrame(updateDom)
  }
}
requestAnimationFrame(updateDom)

到此,raf解決了動畫什么時候開始和最佳循環(huán)循環(huán)間隔的問題源祈,但是代碼具體的在哪個時間執(zhí)行嗎煎源,確是不知道的,只知道動畫在屏幕刷新時候開始香缺。不過手销,mozRequestAnimationFrame()傳遞的函數(shù)也會接收一個參數(shù),是一個時間碼(從1970年1月1日起至今的毫秒數(shù))图张,表示下一次重繪發(fā)生的實際時間锋拖。
如果想知道距離上一次重繪過去的時間,可以查詢mozAnimationStartTime祸轮,不過這個屬性知識Mozilla實現(xiàn)了兽埃。目前chrome和IE都沒有此屬性。這個值包含上一次重繪的時間碼,用傳入回調(diào)函數(shù)的時間碼減去這個時間适袜,就能計算出在屏幕上重繪下一簇變化之前要經(jīng)過多少時間柄错。

function draw(timestamp){
  var differ = timestamp - startTime;//differ確定下一次重繪時間與現(xiàn)在時間的差值
  startTime = timestamp;//把timestamp重寫為這一次的繪制時間
  mozRequestAnimationFrame(draw);
}
var startTime = mozAnimationStartTime;
mozRequestAnimationFrame(draw)

chrome和IE10+都給出了帶前綴的requestAnimationFrame方法實現(xiàn),不過與Mozilla的版本還是有點差異苦酱。
差異1:不回給回調(diào)函數(shù)傳時間碼售貌。
差異2:chrome增加了第二個可選的參數(shù):即將要發(fā)生變化的DOM元素。
chrome提供了一個取消幀動畫的方法疫萤,webkitCancelAnimationFrame(),用于取消之前計劃的重繪操作趁矾。
當然,作為一個新興的API给僵,兼容性問題肯定少不了毫捣。所以實際開發(fā)過程中,請注意兼容性的處理帝际。

requestAnimationFrame的優(yōu)點:
1.多個raf可以并行繪制蔓同。(這一點跟setTimeout和setInterval進入異步隊列有關(guān)系。)
2.在隱藏或者不可見的元素匯總蹲诀,raf將不會進行重繪和回流斑粱,這就意味著更少的CPU和GPU以及內(nèi)存使用量。

  1. 由瀏覽器專門為動畫提供的API脯爪,在運行時瀏覽器會自動優(yōu)化方法的調(diào)用则北,并且如果頁面不是激活狀態(tài)的話矿微,動畫就會暫停,節(jié)省了CPU開銷尚揣。(對于這一點涌矢,本人試了試setTimeout和setInterval,發(fā)現(xiàn)用這兩者做的動畫在不激活的狀態(tài)下也會暫停快骗,不知道是chrome瀏覽器做了優(yōu)化還是說只有chrome是這樣娜庇。)

4.函數(shù)節(jié)流: 在高頻率時間中(resize,scroll等),為了防止在一個刷新間隔內(nèi)發(fā)生多次函數(shù)執(zhí)行方篮,使用raf可保證每個刷新間隔內(nèi)名秀,函數(shù)只能被執(zhí)行一次,這樣既能保證流浪性藕溅,也能更好的節(jié)省函數(shù)執(zhí)行的開銷匕得。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市巾表,隨后出現(xiàn)的幾起案子耗跛,更是在濱河造成了極大的恐慌,老刑警劉巖攒发,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件调塌,死亡現(xiàn)場離奇詭異,居然都是意外死亡惠猿,警方通過查閱死者的電腦和手機羔砾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偶妖,“玉大人姜凄,你說我怎么就攤上這事≈悍茫” “怎么了态秧?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扼鞋。 經(jīng)常有香客問我申鱼,道長,這世上最難降的妖魔是什么云头? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任捐友,我火速辦了婚禮,結(jié)果婚禮上溃槐,老公的妹妹穿的比我還像新娘匣砖。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布猴鲫。 她就那樣靜靜地躺著对人,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拂共。 梳的紋絲不亂的頭發(fā)上牺弄,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機與錄音匣缘,去河邊找鬼猖闪。 笑死鲜棠,一個胖子當著我的面吹牛肌厨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豁陆,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼柑爸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盒音?” 一聲冷哼從身側(cè)響起表鳍,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祥诽,沒想到半個月后譬圣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡雄坪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年厘熟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片维哈。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡绳姨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阔挠,到底是詐尸還是另有隱情飘庄,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布购撼,位于F島的核電站跪削,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏迂求。R本人自食惡果不足惜切揭,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锁摔。 院中可真熱鬧廓旬,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至励背,卻和暖如春春霍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背叶眉。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工址儒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衅疙。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓莲趣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饱溢。 傳聞我的和親對象是個殘疾皇子喧伞,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容