實用的 CSS — 動畫性能對比

歡迎移步個人博客閱讀:《實用的 CSS — 動畫性能對比》css

前言

在現代瀏覽器中,渲染頁面所要負責的線程主要有兩個:主線程和排版線程。html

主線程

  • 運行 JScss3

  • 計算 HTML 元素的 CSS 樣式web

  • 佈局頁面瀏覽器

  • 把頁面元素繪製成一個或多個位圖佈局

  • 把這些位圖移交給排版線程性能

在瀏覽器開始渲染頁面,或者長時間執行某個 JS 時,主線程會一直在忙碌狀態,此時對於用戶的任何輸入或是操做都不會有所響應。動畫

排版線程

  • 經過 GPU 渲染位圖,並顯示在屏幕上spa

  • 向主線程請求更新位圖的可見部分或即將可見的部分線程

  • 判斷出當前頁面處於可見的部分

  • 判斷出即將經過頁面滾動而可見的部分

  • 隨着用戶滾動頁面來移動這些部分

排版線程對於用戶的操做保持快速的響應,廣泛的效率時每秒 60 幀的速度去刷新顯示。

Transtion

下面咱們在網頁中實現一個元素的高度變化的動畫,鼠標懸浮在元素上動畫啓動,直至完成:

<style>
#foo {
  height: 100px;
  width: 100px;
  background: red;
  transition: height 1s linear;
}
#foo:hover {
  height: 200px;
}
</style>
<body>
  <div id="foo"></div>
</body>

經過對上述代碼的觀察,讓咱們來了解一下瀏覽器的兩個線程是如何協同工做的:

圖中橘黃色部分表明操做相對較慢,消耗較大;藍色部分表明操做相對較快,消耗較小

animations-performance-transition.png

從上圖咱們能夠看到,瀏覽器的兩個線程在來回地切換工做,並且橘黃色出現次數較多,這意味着瀏覽器須要處理至關多的工做。

對於瀏覽器而言,因爲元素的高度一直在變化,所以這個動畫的每一幀中,都須要從新佈局 ——> 繪製頁面 ——> 將新的位圖加載到 GPU 中 ——> 顯示。而其中加載到 GPU 是一個相對緩慢的操做。

同時咱們也在經過瀏覽器去查看元素動畫的過程,實際上是由略微卡頓的現象的。

Transform

通過上面的實驗,咱們對 transition 屬性有了比較好的瞭解;同時咱們對上述動畫性能也有一個瞭解。接着我須要在網頁中實現一個元素的大小變化動畫,鼠標懸浮在元素上動畫啓動,直至完成:

<style>
#bar {
  height: 100px;
  width: 100px;
  background: red;
  transition: transform 1s linear;
}
#bar:hover {
  transform: scale(2);
}
</style>
<body>
  <div id="bar"></div>
</body>

完成上述實驗,再讓咱們來看看兩個線程工做的過程:

animations-performance-transform.png

由此咱們能夠看到,兩個線程來回切換的狀況並很少,橘黃色部分出現的次數也較少,藍色部分居絕大部分,這意味着這個動畫效果相較於上面的要流暢不少。

在定義中,transform 是不會使瀏覽器產生從新排版的,所以 transform 不會影響本來的佈局,以及周圍的元素。它會將定義的元素做爲一個總體進行縮放、移動或旋轉等。

基於 transform 這類的特性,瀏覽器在渲染頁面時能夠節省不少沒必要要的開支,例如從新佈局和將位圖傳給 GPU 等工做,這樣就使得動畫更有效率。

總結

當頁面須要位移動畫時,咱們有兩種方案:使用 position 或是 transalte,而這兩種是符合上述狀況的。其中 position 的位移方案與第一個符合,在動畫執行過程當中會使瀏覽器從新渲染;另外一外 transalte 則與第二個符合,在執行動畫時不會發生從新渲染。所以,在須要寫動畫時,咱們須要選擇合適的方案,最好是選擇 scale()rotate()transalte() 等,由於他們具備更好的性能。

參考

W3C: CSS Transforms
W3C: CSS Transitions
css-animations-and-transitions-performance

相關文章
相關標籤/搜索