使用CSS3開啟GPU硬件加速提升網站動畫渲染性能


遇到的問題:

  網站本身設計初衷就沒有打算支持IE8及以下版本瀏覽器,並不是因為代碼兼容性問題,而是真的不想遷就那些懶得更新自己操作系統和瀏覽器的用戶,畢竟是我自己的網站,所以我說了算!哈哈~

  沒有了低版本IE6瀏覽器,就不用顧慮他們的性能問題了,本以為開發會一帆風順,結果”性能問題”竟然出現在了一直以性能出色著稱的Chrome瀏覽器中。

  Chrome下的動畫比IE9和FF都要慢很多,一開始覺得是自己的js邏輯問題,因為要遍歷9個元素並計算他們的坐標。后來嘗試了使用requestAnimationFrame、webWorker和canvas,但情況仍然沒有任何好轉。通過chrome的DevTool中TimeLine監控,發現動畫的代碼邏輯並沒有占用太多資源,反倒是painting消耗了大量的時間,平均才30fps左右。

chrome_timeline_frames_30fps chrome_timeline_frames_30fps

chrome_timeline_frames_30fps
上圖可見主要時間都浪費在painting上了,元素背景圖過大導致。

chrome_timeline_frames_30fps
chrome_timeline_frames_30fps

  上面這幾張圖都是開啟GPU硬件加速之前使用Chrome DevTool Timeline功能中Frames模塊監測到的數據,明顯看到平均幀速率在30fps左右

  其實,chrome對於渲染多張大尺寸圖片方面一直表現疲軟,之前在開發人人小站瀑布流布局模板的時候就遇到過這類問題,chrome中只要存在大量縮放圖片,頁面滾動的時候就會極其卡頓,就像是用一台2004年的電腦訪問一個2014年的網站一樣。chrome對於渲染很多大尺寸圖片(尤其是alphy透明度PNG24圖片)方面有先天的不足,從它版本10+的時候就有開發者在官方平台報過這個Bug,如今chrome已經更新至版本30+,卻依舊沒有完美解決這個頑疾。

解決Chrome動畫”卡頓”的辦法

  為動畫DOM元素添加CSS3樣式-webkit-transform:transition3d(0,0,0)或-webkit-transform:translateZ(0);,這兩個屬性都會開啟GPU硬件加速模式,從而讓瀏覽器在渲染動畫時從CPU轉向GPU,其實說白了這是一個小伎倆,也可以算是一個Hack,-webkit-transform:transition3d和-webkit-transform:translateZ其實是為了渲染3D樣式,但我們設置值為0后,並沒有真正使用3D效果,但瀏覽器卻因此開啟了GPU硬件加速模式。

  這種GPU硬件加速在當今PC機及移動設備上都已普及,在移動端的性能提升是相當顯著地,所以建議大家在做動畫時可以嘗試一下開啟GPU硬件加速。

當然也可以這樣開啟所有瀏覽器的GPU硬件加速:

webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);

webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
-o-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);

 

  使用-webkit-transform:transition3d(0,0,0)開啟GPU硬件加速的chrome中渲染動畫性能明顯順暢了許多,平均能達到55fps左右。無圖無真相:

chrome_timeline_frames_60fps
chrome_timeline_frames_60fps
chrome_timeline_frames_60fps
開啟GPU硬件加速前后幀速率對比
開啟GPU硬件加速前后幀速率對比圖(點擊查看清晰大圖)

chrome詭異的Bug

  對所有動畫DOM元素添加-webkit-transform:transition3d(0,0,0)開啟GPU硬件加速之后,又出現了一個chrome詭異的Bug,當你有多個position:absolute;元素添加-webkit-transform:transition3d(0,0,0);開啟GPU硬件加速之后,會有幾個元素憑空消失,調試許久無果遂Google之,國內暫時沒有人發表過關於這類問題的文章,於是在國外網站找呀找,找到了很多與我遇到同樣問題的人,但都沒有真正靠譜的解決辦法,這可能是跟添加-webkit-transform之后chrome嘗試使用GPU硬件加速有關系,最后還是要等待Chrome官方更新解決了,當前Chrome版本是33。如果誰發現比較好的解決辦法,歡迎提出^_^

其他人遇到的類似問題:
3D CSS transform: translateZ causes elements to disappear in Chrome
Fixed attachment background image flicker/disappear in chrome when coupled with a css transform

如何避免這個問題:

  在使用-webkit-transform嘗試對很多DOM元素編寫3D動畫時,盡量不要對這些元素及他們的父元素使用position:absolute/fixed。(其實這種情況很難避免)
所以我的臨時解決辦法是,減少使用-webkit-transform:transition3d(0,0,0)的DOM元素數量,從9個減至6個便沒有元素消失的現象了。
PS:由於測試環境有限,如果大家發現在你的瀏覽器還有這個Bug,麻煩留言告訴我,萬分感謝!

開啟GPU硬件加速可能觸發的問題:

通過-webkit-transform:transition3d/translateZ開啟GPU硬件加速之后,有些時候可能會導致瀏覽器頻繁閃爍或抖動,可以嘗試以下辦法解決之:

-webkit-backface-visibility:hidden;
-webkit-perspective:1000;

如何監測動畫幀速率

推薦兩種實時監測網頁渲染幀速率的方法:

1.Chrome的DevTool中TimeLine的Frame模塊
chrome_timeline_frames

2.地址欄輸入”chrome:flags”搜索”fps”,將”FPS計數器”開啟,瀏覽器重啟后右上角會實時顯示幀速率。
chrome_fps_counter

我會再過些天單獨寫一篇關於通過Frame模塊監測網站性能的教程,敬請留意^_^

通過-webkit-transform:transition3d/translateZ開啟GPU硬件加速的適用范圍:

  • 使用很多大尺寸圖片(尤其是PNG24圖)進行動畫的頁面。
  • 頁面有很多大尺寸圖片並且進行了css縮放處理,頁面可以滾動時。
  • 使用background-size:cover設置大尺寸背景圖,並且頁面可以滾動時。(詳見:https://coderwall.com/p/j5udlw)
  • 編寫大量DOM元素進行CSS3動畫時(transition/transform/keyframes/absTop&Left)
  • 使用很多PNG圖片拼接成CSS Sprite時

我能想到的暫時只有這五種情況,歡迎大家補充。

總結:

  通過開啟GPU硬件加速雖然可以提升動畫渲染性能或解決一些棘手問題,但使用仍需謹慎,使用前一定要進行嚴謹的測試,否則它反而會大量占用瀏覽網頁用戶的系統資源,尤其是在移動端,肆無忌憚的開啟GPU硬件加速會導致大量消耗設備電量,降低電池壽命等問題。

您還可以參考以下HTML5相關文章:
人人網首頁拖拽上傳詳解(HTML5 Drag&Drop、FileReader API、formdata)
HTML5 Drag&Drop 拖拽、FileReader實例教程
關於HTML 5 canvas 的基礎教程

 PS:http://blog.bingo929.com/transform-translate3d-translatez-transition-gpu-hardware-acceleration.html(感謝彬GO)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM