RequestAnimationFrame確實是實現動畫不可或缺的利器,但是不可以過度的使用。尤其是和一些漸變性的事件相關聯的動畫,比如,Chrome Web Store首頁利用垂直滾軸不斷顯示頁面內容。下面給出一個不太好的例子:
- 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事件的時候,都調用RequestAnimationFrame,雖然瀏覽器會量力而行的執行動畫渲染,但是有兩個沖突的地方,成為了動畫渲染的性能瓶頸。首先,scroll事件調用的頻率,遠遠大約每秒60幀。也就是說,瀏覽器會緩存大量的RequestAnimationFrame事件,導致很多的update函在做無用功。其次,在每次執行RequestAnimationFrame的時候,里面對dom元素的屬性進行了修改,引起了很多的Reflow和Repaint事件,顯然完成所有的Reflow和Repaint時間的遠遠超過16ms。
為了解決第一個問題,首先要將scroll和RequestAnimaitonFrame函數分離,修改后的代碼如下:
- 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事件僅負責將最新的窗口位置,賦值給一個變量。這樣的話,可以避免大量的RequestAnimationFrame事件被緩存,從而真正讓RequestAnimationFrame按照瀏覽器的能力,進行動畫渲染。
對于第二個問題,唯一的辦法,盡量的減少Repaint和Reflow的事件。道理雖然簡單,但是優化難度很大,要求讀者對于Dom的渲染的每個函數都非常熟悉。下面列出幾篇文章,僅供參考:
ClassList for great good.
Breakdown of repaint.
Learning from Twitter
(未完待續)
上文:
HTML5游戲開發 之 循環的控制(2)
HTML5游戲開發 之 循環的控制(1)
HTML5 游戲開發 之 資源加載篇(2)
HTML5 游戲開發 之 資源加載篇(1)
【網站聲明】本站除付費源碼經過測試外,其他素材未做測試,不保證完整性,網站上部分源碼僅限學習交流,請勿用于商業用途。如損害你的權益請聯系客服QQ:2655101040 給予處理,謝謝支持。