使用css3實現動畫來開啟GPU加速


參考文章:
https://www.w3cplus.com/css3/introduction-to-hardware-acceleration-css-animations.html
http://blog.csdn.net/hsany330/article/details/50925260

用CSS3動畫替代JS模擬動畫的好處:

  1. 不占用JS主線程;

  2. 可以利用硬件加速;

  3. 瀏覽器可對動畫做優化(元素不可見時不動畫減少對FPS影響)

下面讓我們來看一個動畫效果,在該動畫中包含了幾個堆疊在一起的球並讓它們沿相同路徑移動。最簡單的方式就是實時調整它們的 lefttop 屬性。我們可以使用JavaScript,但我們將使用CSS動畫來替代。請注意,文中的示例不帶任何前綴,示例中使用了Autoprefixer來確保完整的兼容性。

.ball-running { animation: run-around 4s infinite; } @keyframes run-around { 0%: { top: 0; left: 0; } 25% { top: 0; left: 200px; } 50% { top: 200px; left: 200px; } 75% { top: 200px; left: 0; } } 

這里有一個動畫按例,點擊按鈕啟動一個JavaScript動畫:

點擊“Start Animation”按鈕之后,你會隱約感覺到動畫並不是那么流暢,即使使用電腦上的瀏覽器也會有些卡頓,更不要提在移動端達到 60fps 的流暢效果了。為了解決這個問題,我們可以使用 CSS transform 中的 translate() 來替代 topleft

.ball-running { animation: run-around 4s infinite; } @keyframes run-around { 0%: { transform: translate(0, 0); } 25% { transform: translate(200px, 0); } 50% { transform: translate(200px, 200px); } 75% { transform: translate(0, 200px); } } 

現在動畫看起來流暢多了。這是為什么呢?這是因為 transform 屬性不會觸發瀏覽器的 repaint,而 lefttop 則會一直觸發 repaint,下圖是從 chrome 開發者工具的 timeline 面板監測到的數據:

 
CSS動畫之硬件加速

上圖數據中的綠色條紋表示的就是使用 topleft 實現動畫時瀏覽器發生的 repaint 操作,從中可以看出動畫幀數遠低於 60 幀。

下圖是使用CSS transform 檢測到的數據:

 
CSS動畫之硬件加速

如你所見,動畫演示期間並沒有過多的 repaint 操作。

從 chrome 的開發者工具按 ESC 之后選擇 “rendering” 面板,我們可以通過選中“Enable piant flashing”來進一步監測 repaint 操作。開啟該選項后,頁面中的 repaint 區域就會被綠色蒙版高亮顯示出來。重新使用 topleft 的示例演示的話,你會發現包裹球的那塊區域會一直閃爍綠色的蒙版。

 
CSS動畫之硬件加速

另一方面,在使用 transform的示例中,綠色蒙版只會在動畫開始和結束的時候出現。

那么,為什么 transform 沒有觸發 repaint 呢?簡而言之,transform 動畫由GPU控制,支持硬件加速,並不需要軟件方面的渲染。

瀏覽器接收到頁面文檔后,會將文檔中的標記語言解析為DOM樹。DOM樹和CSS結合后形成瀏覽器構建頁面的渲染樹。渲染樹中包含了大量的渲染元素,每一個渲染元素會被分到一個圖層中,每個圖層又會被加載到GPU形成渲染紋理,而圖層在GPU中 transform 是不會觸發 repaint 的,這一點非常類似3D繪圖功能,最終這些使用 transform 的圖層都會由獨立的合成器進程進行處理

在我們的示例中,CSS transform 創建了一個新的復合圖層,可以被GPU直接用來執行 transform 操作。在chrome開發者工具中開啟“show layer borders”選項后,每個復合圖層就會顯示一條黃色的邊界:

示例中的球就處於一個獨立的復合圖層,移動時的變化也是獨立的:

 
CSS動畫之硬件加速

此時,你也許會問:瀏覽器什么時候會創建一個獨立的復合圖層呢?事實上一般是在以下幾種情況下:

  • 3D 或者 CSS transform
  • <video><canvas> 標簽
  • CSS filters
  • 元素覆蓋時,比如使用了 z-index 屬性

等一下,上面的示例使用的是 2D transition 而不是 3D 的 transforms 啊?這個說法沒錯,所以在timeline中我們可以看到:動畫開始和結束的時候發生了兩次 repaint 操作。

 
CSS動畫之硬件加速

3D 和 2D transform 的區別就在於,瀏覽器在頁面渲染前為3D動畫創建獨立的復合圖層,而在運行期間為2D動畫創建。動畫開始時,生成新的復合圖層並加載為GPU的紋理用於初始化 repaint。然后由GPU的復合器操縱整個動畫的執行。最后當動畫結束時,再次執行 repaint 操作刪除復合圖層。

使用 GPU 渲染元素

並不是所有的CSS屬性都能觸發GPU的硬件加速,實際上只有少數屬性可以,比如下面的這些:

  • transform
  • opacity
  • filter

強制使用GPU渲染

為了避免 2D transform 動畫在開始和結束時發生的 repaint 操作,我們可以硬編碼一些樣式來解決這個問題:

.example1 { transform: translateZ(0); } .example2 { transform: rotateZ(360deg); } 

這段代碼的作用就是讓瀏覽器執行 3D transform。瀏覽器通過該樣式創建了一個獨立圖層,圖層中的動畫則有GPU進行預處理並且觸發了硬件加速。

開啟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


轉載於簡書Evan_zhan, 原文地址


免責聲明!

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



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