本文章為綜合其它資料所得。
根據Google Developer,Chromium項目里,渲染線程分為main thread和compositor thread。
如果CSS動畫只是改變transforms
和opacity
,這時整個CSS動畫得以在compositor thread完成(而JS動畫則會在main thread執行,然后觸發compositor進行下一步操作)
在JS執行一些昂貴的任務時,main thread繁忙,CSS動畫由於使用了compositor thread可以保持流暢,可參考adobe的博客。
在主線程中,維護了一棵Layer樹(LayerTreeHost),管理了TiledLayer,在compositor thread,維護了同樣一顆LayerTreeHostImpl,管理了LayerImpl,這兩棵樹的內容是拷貝關系。因此可以彼此不干擾,當Javascript在main thread操作LayerTreeHost的同時,compositor thread可以用LayerTreeHostImpl做渲染。當Javascript繁忙導致主線程卡住時,合成到屏幕的過程也是流暢的。
為了實現防假死,鼠標鍵盤消息會被首先分發到compositor thread,然后再到main thread。這樣,當main thread繁忙時,compositor thread還是能夠響應一部分消息,例如,鼠標滾動時,加入main thread繁忙,compositor thread也會處理滾動消息,滾動已經被提交的頁面部分(未被提交的部分將被刷白)。
CSS動畫比JS流暢的前提:
- 在Chromium基礎上的瀏覽器中
- JS在執行一些昂貴的任務
- 同時CSS動畫不觸發layout或paint
在CSS動畫或JS動畫觸發了paint或layout時,需要main thread進行Layer樹的重計算,這時CSS動畫或JS動畫都會阻塞后續操作。
參考CSS Triggers,只有如下屬性的修改才符合“僅觸發Composite,不觸發layout或paint”:
- backface-visibility
- opacity
- perspective
- perspective-origin
- transfrom
所以只有用上了3D加速或修改opacity時,才有機會用得上CSS動畫的這一優勢。
因此,在大部分應用場景下,效率角度更值得關注的還是下列問題。
- 是否導致layout
- repaint的面積
- 是否是有高消耗的屬性(css shadow等)
- 是否啟用硬件加速
那么Chromium以外的其他瀏覽器呢?CSSTrick里比較了一次效率。
Animated properties | JS-based Animation更快 | CSS-based Animation更快 |
top, left, width, height | Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS 6), iPad 3 (iOS7), Samsung Galaxy Tab 2, Chrome, Firefox, Safari, Opera, Kindle Fire HD, IE11 | (none) |
translate, scale | Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS7), Samsung Galaxy Tab 2, Firefox, Opera, IE11 | iPad 3 (iOS6), Safari, Chrome |
可以看到,Chromium以外的其他瀏覽器沒有這方面的CSS動畫效率的優化。盡管MSDN提到“它可提供更好的呈現性能”,但測試並沒有支持這一點。
現今CSS動畫和JS動畫主要的不同點是
- 功能涵蓋面,JS比CSS3大
- 定義動畫過程的
@keyframes
不支持遞歸定義,如果有多種類似的動畫過程,需要調節多個參數來生成的話,將會有很大的冗余(比如jQuery Mobile的動畫方案),而JS則天然可以以一套函數實現多個不同的動畫過程 - 時間尺度上,
@keyframes
的動畫粒度粗,而JS的動畫粒度控制可以很細 - CSS3動畫里被支持的時間函數非常少,不夠靈活
- 以現有的接口,CSS3動畫無法做到支持兩個以上的狀態轉化
- 定義動畫過程的
- 實現/重構難度不一,CSS3比JS更簡單,性能調優方向固定
- 對於幀速表現不好的低版本瀏覽器,CSS3可以做到自然降級,而JS則需要撰寫額外代碼
- CSS動畫有天然事件支持(
TransitionEnd
、AnimationEnd
,但是它們都需要針對瀏覽器加前綴),JS則需要自己寫事件 - CSS3有兼容性問題,而JS大多時候沒有兼容性問題