RequestAnimationFrame確實是實現(xiàn)動畫不可或缺的利器,但是不可以過度的使用。尤其是和一些漸變性的事件相關(guān)聯(lián)的動畫,比如,Chrome Web Store首頁利用垂直滾軸不斷顯示頁面內(nèi)容。下面給出一個不太好的例子:
- function onScroll() {
- update();
- }
- function update() {
-
- // assume domElements has been declared
- // by this point :)
- for(var i = 0; i < domElements.length; i++) {
-
- // read offset of DOM elements
- // to determine visibility - a reflow
-
- // then apply some CSS classes
- // to the visible items - a repaint
-
- }
- }
- window.addEventListener(‘scroll’, onScroll, false);
上面這個例子,每次scroll事件的時候,都調(diào)用RequestAnimationFrame,雖然瀏覽器會量力而行的執(zhí)行動畫渲染,但是有兩個沖突的地方,成為了動畫渲染的性能瓶頸。首先,scroll事件調(diào)用的頻率,遠(yuǎn)遠(yuǎn)大約每秒60幀。也就是說,瀏覽器會緩存大量的RequestAnimationFrame事件,導(dǎo)致很多的update函在做無用功。其次,在每次執(zhí)行RequestAnimationFrame的時候,里面對dom元素的屬性進(jìn)行了修改,引起了很多的Reflow和Repaint事件,顯然完成所有的Reflow和Repaint時間的遠(yuǎn)遠(yuǎn)超過16ms。
為了解決第一個問題,首先要將scroll和RequestAnimaitonFrame函數(shù)分離,修改后的代碼如下:
- var latestKnownScrollY = 0;
- function onScroll() {
- latestKnownScrollY = window.scrollY;
- }
-
- function update() {
- requestAnimationFrame(update);
- var currentScrollY = latestKnownScrollY;
-
- // read offset of DOM elements
- // and compare to the currentScrollY value
- // then apply some CSS classes
- // to the visible items
- }
-
- // kick off
- requestAnimationFrame(update);
上面的代碼,scroll事件僅負(fù)責(zé)將最新的窗口位置,賦值給一個變量。這樣的話,可以避免大量的RequestAnimationFrame事件被緩存,從而真正讓RequestAnimationFrame按照瀏覽器的能力,進(jìn)行動畫渲染。
對于第二個問題,唯一的辦法,盡量的減少Repaint和Reflow的事件。道理雖然簡單,但是優(yōu)化難度很大,要求讀者對于Dom的渲染的每個函數(shù)都非常熟悉。下面列出幾篇文章,僅供參考:
ClassList for great good.
Breakdown of repaint.
Learning from Twitter
(未完待續(xù))
上文:
HTML5游戲開發(fā) 之 循環(huán)的控制(2)
HTML5游戲開發(fā) 之 循環(huán)的控制(1)
HTML5 游戲開發(fā) 之 資源加載篇(2)
HTML5 游戲開發(fā) 之 資源加載篇(1)
【網(wǎng)站聲明】本站除付費源碼經(jīng)過測試外,其他素材未做測試,不保證完整性,網(wǎng)站上部分源碼僅限學(xué)習(xí)交流,請勿用于商業(yè)用途。如損害你的權(quán)益請聯(lián)系客服QQ:2655101040 給予處理,謝謝支持。