新式瀏覽器可以低成本為兩個 CSS 屬性製作動畫:transform 和 opacity。
如果動畫包含其他項目,您可能無法達到每秒 60 個影格的流暢度。這篇文章說明瞭原因。
動畫效能和影格速率
普遍認為在網頁上製作動畫時,目標影格速率應為每秒 60 個影格。 這個影格速率可確保動畫看起來流暢。在網頁上,影格是指更新及重新繪製畫面所需的所有工作完成時間。如果每個影格未在 16.7 毫秒內完成 (1000 毫秒 / 60 ≈ 16.7),使用者就會感覺到延遲。
算繪管道
如要在網頁上顯示內容,瀏覽器必須依序完成下列步驟:
- 樣式:計算套用至元素的樣式。
- 版面配置:為每個元素產生幾何圖形和位置。
- 繪製:填滿每個元素的像素。
- 合成:將元素分成圖層,並將圖層繪製到畫面上。
這四個步驟稱為瀏覽器的「算繪管道」。
如果您在已載入的網頁上製作動畫,這些步驟就必須再次執行。這項程序會從必須變更的步驟開始,以便進行動畫。
如前所述,這些步驟是循序執行。 舉例來說,如果您為會變更版面配置的項目設定動畫,繪製和合成步驟也必須重新執行。因此,為會變更版面配置的項目加上動畫效果,比為只會變更合成的項目加上動畫效果更耗費資源。
為版面配置屬性套用動畫
版面配置變更會計算受變更影響的所有元素幾何 (位置和大小)。如果變更某個元素,可能需要重新計算其他元素的幾何圖形。舉例來說,如果您變更 <html> 元素的寬度,任何子項都可能會受到影響。
由於元素溢位會互相影響,因此樹狀結構中較下方的變更,有時會導致版面配置運算一路回溯到頂端。
可見元素樹越大,執行版面配置計算所需的時間就越長。
為繪製屬性加上動畫效果
繪製:決定元素在畫面上繪製順序的程序。這通常是管道中執行時間最長的作業。
現代瀏覽器中的繪圖作業大多是由軟體點陣化程式完成。視應用程式中的元素分組方式而定,除了變更的元素外,其他元素可能也需要繪製。
為複合屬性套用動畫
合成:將網頁分成多個圖層,將網頁外觀資訊轉換為像素 (點陣化),然後將圖層組合在一起,建立網頁 (合成)。
因此,opacity 屬性才會列入動畫製作成本較低的項目清單中。
只要這個屬性位於自己的圖層中,GPU 就能在合成步驟中處理變更。
Chromium 版瀏覽器和 WebKit 會為任何具有 CSS 轉換或動畫的元素建立新圖層。opacity
什麼是圖層?
將要製作動畫或轉場效果的項目放在新圖層上,瀏覽器只需要重新繪製這些項目,不必重新繪製其他項目。您可能熟悉 Photoshop 的圖層概念,其中包含可一起移動的一堆元素。瀏覽器算繪層的概念與此類似。
瀏覽器會判斷哪些元素應位於新圖層,但如果判斷錯誤,您也可以強制建立圖層。如要瞭解如何建立高效能動畫,請參閱「如何建立高效能動畫」。不過,建立新圖層時應謹慎操作,因為每個圖層都會使用記憶體。在記憶體有限的裝置上,建立新圖層可能會導致效能問題,比您嘗試解決的問題更嚴重。 此外,每個圖層的紋理都必須上傳至 GPU。 因此,您很可能會遇到 CPU 和 GPU 之間的頻寬限制。
CSS 與 JavaScript 的效能比較
您可能會想知道,就效能而言,使用 CSS 或 JavaScript 製作動畫是否比較好?
CSS 型動畫和 Web Animations (在支援 API 的瀏覽器中) 通常會在稱為「合成器執行緒」的執行緒上處理。這與瀏覽器的主要執行緒不同,後者會執行樣式、版面配置、繪製和 JavaScript。也就是說,如果瀏覽器在主執行緒上執行耗用大量資源的工作,這些動畫仍可繼續播放,不會中斷。
如本文所述,在許多情況下,合成器執行緒也能處理變形和不透明度的其他變更。
如果任何動畫觸發繪製、版面配置或兩者,主執行緒就必須執行工作。CSS 和 JavaScript 動畫都是如此,而且版面配置或繪製的負荷可能會遠超過與 CSS 或 JavaScript 執行相關的任何工作,因此這個問題就沒有意義了。