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

Paul Lewis

避免繪製顏料能達到自然流暢的影格速率,尤其對於行動裝置而言更是如此。但有時候,最不尋常的地方會有繪製痕跡。本文將說明動畫 GIF 為何可能造成不必要的繪製,以及值得套用的簡單修正方法。

情感層疊

如您所知,新式瀏覽器可能會將一組 DOM 元素繪製成個別的「圖片」,稱為圖層。有時候,系統會為整個網頁設定單一圖層,有時甚至可能多達數百個,甚至多達數千個!

將 DOM 元素歸入同一個圖層,且其中一個元素在視覺上有所改變時,除了繪製變更的元素外,還要在「圖層中與已變更的元素重疊」中繪製所有其他元素。將一件事以另一端繪製,會使被覆寫的像素永久「遺失」;如要再次繪製原始像素,就必須重新繪製。

因此,我們有時會想要將某個元素與其他元素隔離,這樣繪製時就不需要重新繪製其他「沒有」變更的元素。舉例來說,如果您將固定頁面標頭與可捲動內容結合,就必須在每次內容捲動時重新繪製標題,以及新顯示的內容。藉由將標頭放在個別圖層中,瀏覽器可以最佳化捲動效果。捲動畫面時,瀏覽器可以自行移動圖層 (可能藉助 GPU 的輔助),並避免各層重新繪製。

每增加一個層,就會增加記憶體用量,並增加效能負擔,我們的目標是盡可能將網頁分組,同時維持良好的效能。

這與 GIF 動畫有什麼關聯?

來看看下圖:

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

這是簡易應用程式的潛在圖層設定。這裡有四個圖層:介面元素三個 (第 2 到 4 層) 是介面元素;後層則是載入器,以 GIF 動畫呈現。在正常流程中,您會在應用程式載入時顯示載入器 (第 1 層),之後一切結束後,就會顯示其他圖層。不過,重點如下:你必須隱藏 GIF 動畫。

但為什麼一定要把它隱藏?!

好問題!在理想情況下,瀏覽器只會檢查 GIF 的顯示設定,避免自動繪圖。可惜的是,比起單純繪圖,檢查 GIF 動畫是否遭到遮蔽或是否可見,通常繪畫還昂貴。

在最好的情況下,GIF 會放在專屬的圖層上,瀏覽器只需繪製並上傳至 GPU,但最糟的情況是,所有元素可能會歸入同一個圖層,瀏覽器就必須重新繪製每個元素。處理完成後,仍須將所有內容上傳至 GPU。這項操作適用於每個 GIF 影格,但使用者看不到 GIF!

在電腦上,這類繪製行為可能會因 CPU 和 GPU 效能更強大,且兩者之間有充足的頻寬來傳輸資料,因此或許會讓電腦無法發揮最佳效果。不過,在行動裝置上,繪畫需要極高的成本,因此請務必謹慎小心。

哪些瀏覽器會受到影響?

不過,由於瀏覽器和瀏覽器之間的行為有所不同,現在 Chrome、Safari 和 Opera 會重新繪製影片,即使 GIF 模糊不清也一樣。另一方面,Firefox 發現 GIF 圖片模糊不清,因此不需要重新繪製。Internet Explorer 仍存在黑盒子,甚至在 IE11 中仍然存在,因為 F12 工具仍在開發中,因此沒有跡象顯示是否有重新繪製。

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

最簡單的方法是在 Chrome 開發人員工具中使用「顯示繪製矩形」。載入開發人員工具,按下右下角的齒輪 (銷貨成本圖示),然後在「轉譯」部分選擇「顯示油漆矩形」

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

現在,您只需尋找如下的紅色矩形即可:

開發人員工具的繪製矩形提示的是 GIF 動畫問題以及紅色矩形。
圖 3:開發人員工具的顯示繪製矩形提示的是有紅色矩形的 GIF 動畫問題。

螢幕上的小紅色方塊顯示 Chrome 正在重新繪製內容。由於其他元素背後有一個載入器 GIF,因此當您看到如下的紅色方塊時,您必須隱藏這些元素,然後檢查 GIF 動畫是否在旋轉。如果已經設定,則必須彈出一些 CSS 或 JavaScript,才能將 display: nonevisibility: hidden 套用至該元素或其父項元素。當然,如果它只是背景圖片,請務必將其移除。

如想在實際網站上查看這項行為的範例,請前往 Allegro,每個產品的圖片都有經過模糊處理的載入器 GIF,而非明確隱藏。

結論

如果達到 60fps,就「只」執行轉譯網頁所需的作業,甚至不會更多。消除過量的顏料是實現此目標的重要步驟。持續執行的 GIF 動畫可能會觸發不必要的繪製,您可以使用開發人員工具的「顯示繪製矩形」工具輕鬆找出並偵錯。

你就好了嗎?你決定不讓別人載入動畫的貓咪 GIF 動畫,你知道嗎?