避免不必要的繪製 - 動畫 GIF 版本

Paul Lewis

避免繪圖是達成流暢的畫面更新率的關鍵,特別是在行動裝置上。不過,有時油漆會出現在最不尋常的地方。本文將探討 GIF 動畫為何可能導致不必要的繪圖作業,並提供簡單的修正方式。

層層疊疊的可愛

您可能知道,現代瀏覽器可能會將一組 DOM 元素繪製為個別的「圖片」,稱為圖層。有時整個網頁只有一個圖層,有時則有數百個,甚至在少數情況下有數千個!

當 DOM 元素組合成一個圖層,其中一個元素的視覺效果發生變化時,我們最終不僅要繪製變更的元素,還要繪製圖層中與變更元素重疊的所有其他元素。在某個圖層上繪製圖案時,覆蓋的像素會永久「遺失」,如果您想找回原始像素,就必須重新繪製。

因此,有時我們會將某個元素與其他元素分開,這樣在繪製時,我們就不需要重新繪製「未」變更的其他元素。舉例來說,如果您將固定的網頁標頭與可捲動的內容結合,每次捲動內容時,您都必須重新繪製標頭和新顯示的內容。將標頭放在個別圖層中,瀏覽器就能最佳化捲動功能。捲動時,瀏覽器可以移動圖層 (可能會使用 GPU 的協助),並避免重繪任何圖層。

每增加一個圖層,記憶體用量和效能開銷就會增加,因此目標是盡可能將網頁分組為較少的圖層,同時維持良好的效能。

這一切與 GIF 動畫有何關聯?

我們來看看這張圖片:

網頁應用程式分為四個層。
圖 1:將網路應用程式細分為四個層。

這是簡單應用程式的潛在圖層設定。此處有四個圖層:其中三個 (圖層 2 到 4) 是介面元素;後方圖層是載入器,剛好是動畫 GIF。在一般流程中,您會在應用程式載入時顯示載入器 (第 1 層),然後在所有作業完成後顯示其他層。但重點是:你必須隱藏動畫 GIF。

但為什麼我需要隱藏它?

好問題!在理想情況下,瀏覽器會自動檢查 GIF 的顯示狀態,並避免自動繪製。很遺憾,檢查動畫 GIF 是否會在畫面上遮蔽或顯示,通常比單純繪製動畫 GIF 的運算成本更高,因此會繪製動畫 GIF。

在最佳情況下,GIF 會位於其專屬的圖層,瀏覽器只需將其繪製並上傳至 GPU。但在最糟的情況下,所有元素都可能會被分組至單一圖層,瀏覽器就必須重新繪製每個元素。完成後,它仍需要將所有內容上傳至 GPU。即使使用者根本看不到 GIF,系統仍會為每個 GIF 影格執行上述所有工作。

在電腦上,您可能可以使用這種繪圖行為,因為 CPU 和 GPU 效能更強大,且兩者之間有充足的頻寬可用於傳輸資料。不過,在行動裝置上,繪圖的成本非常高,因此請務必謹慎使用。

這項異動會影響哪些瀏覽器?

如同往常,不同瀏覽器的行為有所差異。目前 Chrome、Safari 和 Opera 都會重新繪製,即使 GIF 已模糊處理也一樣。另一方面,Firefox 會判斷 GIF 已模糊處理,因此不需要重新繪製。Internet Explorer 仍是個黑盒子,即使在 IE11 中,由於 F12 工具仍在開發中,因此無法得知是否有重繪作業。

如何判斷是否有這個問題?

最簡單的方法是在 Chrome 開發人員工具中使用「Show paint rectangles」(顯示繪圖矩形)。載入「DevTools」,然後按下右下角的齒輪圖示 (齒輪圖示),並選擇「Rendering」部分下方的「Show paint rectangles」

在 Chrome 開發人員工具中啟用「顯示繪製矩形區」
圖 2:在 Chrome 開發人員工具中啟用「顯示繪圖矩形」功能。

你只需要尋找如下所示的紅色矩形:

開發人員工具的「顯示繪製矩形」功能會以紅色矩形提示動畫 GIF 的問題。
圖 3:開發人員工具的「Show Paint Rectangles」功能會以紅色矩形提示動畫 GIF 問題。

畫面上的紅色小方塊表示 Chrome 正在重新繪製某些內容。您知道其他元素後面隱藏著載入器 GIF,因此當您看到如下所示的紅色方塊時,請隱藏可見的元素,並確認是否已讓動畫 GIF 旋轉。如果您有,則需要彈出一些 CSS 或 JavaScript,將 display: nonevisibility: hidden 套用至該元素或其父項元素。當然,如果只是背景圖片,那麼請務必移除。

如要查看實際網站中的這項行為,請參考 Allegro,每張產品圖片都會顯示載入器 GIF,但會遮蔽而非明確隱藏。

結論

要達到 60fps,就執行轉譯網頁所需的作業,移除多餘的繪圖是達成此目標的關鍵步驟。繼續執行的 GIF 動畫可能會觸發不必要的繪製作業,您可以使用 DevTools 的「Show paint rectangles」工具,輕鬆找出並偵錯這些不必要的繪製作業。

你不會讓動畫小貓載入器 GIF 永遠執行,對吧?