在 CSS 動畫中使用硬件加速

近些年,我們總是聽到硬件加速,以及它如何幫助我們提升網頁的動畫性能,讓網頁動畫變得更好,在移動端更流暢。但是我想一大部分經驗少的工程師是不知道硬件加速是如何工作的以及我們如何使用它來幫助我們讓動畫變得更流暢。

在GPU渲染元素

並不是所有的CSS屬性變化都會直接在GPU處理。只有下面的屬性會這樣處理:

  • transform
  • opacity
  • filter

因此爲了頁面更加流暢,高性能的動畫,我們需要儘可能的使用GPU來處理

通過-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時

使用硬件加速需要注意的地方

天下沒有免費的午餐。對於硬件加速,目前有幾個問題

Memory

大部分重要的問題都是關於內存。GPU處理過多的內容會導致內存問題。這在移動端和移動端瀏覽器會導致崩潰和消耗更多的電量。 因此,通常不會對所有的元素使用硬件加速。

Font rendering

在GPU渲染字體會導致抗鋸齒無效。這是因爲GPU和CPU的算法不同。因此如果你不在動畫結束的時候關閉硬件加速,會產生字體模糊

The Near Future

有必要使用transform hack的地方是提高性能。瀏覽器自身也提供了優化的功能,這也就是will-change屬性。這個功能允許你告訴瀏覽器這個屬性會發生變化,因此瀏覽器會在開始之前對其進行優化。

will-chang屬性需要注意的地方

  1. 不要將 will-change 應用到太多元素上:瀏覽器已經盡力嘗試去優化一切可以優化的東西了。有一些更強力的優化,如果與 will-change 結合在一起的話,有可能會消耗很多機器資源,如果過度使用的話,可能導致頁面響應緩慢或者消耗非常多的資源。

  2. 有節制地使用:通常,當元素恢復到初始狀態時,瀏覽器會丟棄掉之前做的優化工作。但是如果直接在樣式表中顯式聲明瞭 will-change 屬性,則表示目標元素可能會經常變化,瀏覽器會將優化工作保存得比之前更久。所以最佳實踐是當元素變化之前和之後通過腳本來切換 will-change 的值

  3. 不要過早應用 will-change 優化:如果你的頁面在性能方面沒什麼問題,則不要添加 will-change 屬性來榨取一丁點的速度。 will-change 的設計初衷是作爲最後的優化手段,用來嘗試解決現有的性能問題。它不應該被用來預防性能問題。過度使用 will-change 會導致大量的內存佔用,並會導致更復雜的渲染過程,因爲瀏覽器會試圖準備可能存在的變化過程。這會導致更嚴重的性能問題。

  4. 給它足夠的工作時間:這個屬性是用來讓頁面開發者告知瀏覽器哪些屬性可能會變化的。然後瀏覽器可以選擇在變化發生前提前去做一些優化工作。所以給瀏覽器一點時間去真正做這些優化工作是非常重要的。使用時需要嘗試去找到一些方法提前一定時間獲知元素可能發生的變化,然後爲它加上 will-change 屬性。

.sidebar {
  will-change: transform;
}

以上示例在樣式表中直接添加了 will-change 屬性,會導致瀏覽器將對應的優化工作一直保存在內存中,這其實是不必要的,前面我們已經看過爲什麼應該避免這樣的做法。下面是另一個展示如何使用腳本正確地應用 will-change 屬性的示例,在大部分的場景中,你都應該這樣做。

var el = document.getElementById('element');

// 當鼠標移動到該元素上時給該元素設置 will-change 屬性
el.addEventListener('mouseenter', hintBrowser);
// 當 CSS 動畫結束後清除 will-change 屬性
el.addEventListener('animationEnd', removeHint);

function hintBrowser() {
  // 填寫上那些你知道的,會在 CSS 動畫中發生改變的 CSS 屬性名們
  this.style.willChange = 'transform, opacity';
}

function removeHint() {
  this.style.willChange = 'auto';
}

但是,如果某個應用在按下鍵盤的時候會翻頁,比如相冊或者幻燈片一類的,它的頁面很大很複雜,此時在樣式表中寫上 will-change 是合適的。這會使瀏覽器提前準備好過渡動畫,當鍵盤按下的時候就能立即看到靈活輕快的動畫。

.slide {
  will-change: transform;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章