Web動畫性能指南

Web動畫性能指南 Beta
Animation performance guide book for the (mobile) web
引言
隨着網頁功能變得愈發複雜和精細,以及手機端H5發展中所遇到的硬件性能瓶頸,網頁的運行時性能問題變得越來越突出。而用戶對於網頁運行時性能最直觀的感受,莫過於UI操作的流暢程度。流暢或卡頓,爽或不爽,皆在於每個UI動畫細節之間。本文旨在幫助理解動畫卡頓與流暢的原因,卡頓問題的調試方法,以及從實踐中總結出實現流暢動畫的規律。爲構建操作流暢的網頁提供參考。

索引
量化動畫的流暢程度
瞭解瀏覽器的渲染機制
動畫調優的策略與技巧
量化動畫的流暢程度
動畫的實現原理,是利用了人眼的“視覺暫留”現象,在短時間內連續播放數幅靜止的畫面,使肉眼因視覺殘象產生錯覺,而誤以爲畫面在“動”。

動畫相關的幾個概念

幀:在動畫過程中,每一幅靜止畫面即爲一“幀”。
幀率:即每秒鐘播放的靜止畫面的數量,單位是fps(Frame per second)。
幀時長:即每一幅靜止畫面的停留時間,單位一般是ms(毫秒)。
跳幀(掉幀/丟幀):在幀率固定的動畫中,某一幀的時長遠高於平均幀時長,導致其後續數幀被擠壓而丟失的現象。
身邊的幀率(頻率):

10 FPS 達成基本視覺暫留
25~30 FPS 傳統廣播電視信號
60 FPS 瀏覽器渲染刷新頻率
60~85 HZ 顯示器刷新頻率
100 HZ 日光燈管閃爍頻率
幀率能反映動畫的流暢程度

在網頁中,幀率能夠達到50~60fps的動畫將會相當流暢,讓人倍感舒適。
幀率在30~50fps之間的動畫,因各人敏感程度不同,舒適度因人而異。
幀率在30fps以下的動畫,讓人感覺到明顯的卡頓和不適感。
幀率波動很大的動畫,亦會使人感覺到卡頓。
用幀率量化動畫流暢度的幾個例子

幀率穩定在60fps左右的流暢動畫

幀率穩定但低於30fps的卡頓動畫(幀率低導致卡頓)

平均幀率高,但存在跳幀現象的卡頓動畫(幀率不穩定導致卡頓)

幾款幀率監測工具

Stats.js,偵聽全局或指定位置的幀率,JS實現,所有瀏覽器可用
Stats.js panel

Chrome自帶的幀率監測工具,用於偵聽全局幀率,以及頁面重繪耗時
Chrome fps panel Chrome ms panel

Chrome Console

Chrome Timeline,殺手級監測 & 調試工具
Chrome Console

小結

幀率能夠量化動畫的流暢程度,流暢的動畫一般具備兩個特點:

幀率高(接近60fps最佳)
幀率穩定,波動少(極少出現跳幀現象)
ps: 或許有同學會有疑問:爲什麼電影/電視的幀率小於30fps,但依然感覺很流暢? 這個問題可以參閱這條知乎回答

因此,準確來說,前面所說的最佳幀率60fps,以及幀率小於30fps的動畫出現卡頓感覺,前提是動畫中沒有加入模糊等特效。

瞭解瀏覽器的渲染機制
每當性能提升工作遇到瓶頸時,我們總是會嘗試從底層實現機制中尋找突破口。動畫性能優化也不例外,想要將動畫性能提升到極致,首先我們需要知道瀏覽器是如何渲染每一幀的。

瀏覽器的渲染引擎

各廠出品的瀏覽器所用的渲染引擎不盡相同: IE使用Trident ,FireFox使用Gecko ,Safari使用WebKit ,Chrome 28+ 和 Opera 15+使用的是Blink(WebKit的分支)。

來看兩個例子:

Webkit的渲染流程 Webkit render flow

Gecko的渲染流程 Gecko render flow

雖然瀏覽器款式如此之多,但當我們對比WebKit和Gecko這兩款引擎的工作流程,會發現二者大體的流程以及一些關鍵環節還是基本相同的。

幾個關鍵的工作環節:

HTML解析(Parse HTML)
解析CSS(Parse CSS)
生成渲染樹(Render Tree / Frame Tree)
排版/重排(Layout/Reflow)
繪圖/重繪(Painting)
各款渲染引擎的基本工作流程可以抽象爲下圖: Render flow abstract

可見,對於通過修改HTML元素CSS樣式實現的動畫,每修改一次CSS,瀏覽器就會做一次上圖中CSS解析及其隨後的操作。 (但並不是每一次對CSS的修改都會重新排版和繪圖)

通過工具監測瀏覽器渲染行爲

目前對瀏覽器渲染行爲的監測,實現較好的是Chrome與Safari,並且這兩者能遠程調試Android和iOS設備中的Chrome和Safari瀏覽器(Chrome在Android 4.0後開始支持)。

藉助Chrome和Safari的Timeline工具,分析耗時較長的幀,我們便能定位到渲染耗時長的原因,並針對問題原因尋找解決方案。

Chrome Timeline
Chrome Timeline

Safari Timeline
Safari Timeline

現代瀏覽器的硬件加速渲染通道以及層模型(Layer model)

近些年來,現代瀏覽器藉助於顯卡的優勢改變了渲染操作:通常被籠統的稱爲“硬件加速(hardware acceleration)”。

以Chrome爲例,在硬件加速渲染通道下,複雜的頁面會被分爲多個層(Layer), Chrome對各個層分別進行排版、繪圖,再將繪圖結果作爲“紋理”上傳至GPU, 由GPU完成層的3D變換(transform)等操作,最後再將GPU渲染好的層圖像進行復合操作(Compesite Layers),得到最終的畫面結果。 因此,通過3D變換實現的位移、旋轉、縮放將不會觸發瀏覽器重繪(除非層的內容發生改變)。

可見,可以避免重繪的層模型對於動畫調優有着重大意義。

通過工具“看到”層

Chrome
Chrome Layer

Safari
Safari Layer

通過分層減小重繪面積

Chrome Layer root

如何創建新的層

從目前來看(Chrome、Safari等現代瀏覽器仍在不斷迭代演進),以下情況下元素會創建自己的層(包括但不限於以下情況,待完善):

觸發普通元素的分層:
transform:translate3d屬性(如transform:translateZ(0))
自帶單獨分層的元素
使用加速視頻解碼的元素
>元素
Flash等插件
動畫調優的策略與技巧
提升每一幀性能(縮短幀時長,提高幀率)
避免頻繁的重排。
避免大面積的重繪。
優化JS運行性能。
保證幀率平穩(避免跳幀)
不在連續的動畫過程中做高耗時的操作(如大面積重繪、重排、複雜JS執行),避免發生跳幀。
若高耗時操作無法避免,則嘗試化解,比如:
將高耗時操作放在動畫開始或結尾處。
將高耗時操作分攤至動畫的每一幀中處理。
針對硬件加速渲染通道的優化
通過層的變化效果(如transform)實現位移、縮放等動畫,可避免重繪。
合理劃分層,動靜分離,可避免大面積重繪。
使用分層優化動畫時,需要留意內存消耗情況(通過Safari調試工具)。
低性能設備優先調試
Android設備優先調試:移動設備的硬件配置一般低於桌面設備,而移動端設備中,Android設備相比於iOS設備性能普遍較差,因此在Andorid設備下性能問題更加明顯,幸運的是Android可以藉助Chrome自帶的遠程調試工具方便調試動畫性能(Android 4.0+),所以優先調試Android設備可以更早地發現問題,並能更方便地解決問題。
本文仍在更新中,歡迎通過Github Watch關注更新動態

有更多想法,歡迎交流,想要拍磚、指正、提建議,請戳這裏。

參考資料
High Performance Animations
How Browsers Work: Behind the scenes of modern web browsers
Accelerated Rendering in Chrome
Performance profiling with the Timeline
Profiling Long Paint Times with DevTools’ Continuous Painting Mode
Scrolling Performance
GPU Accelerated Compositing in Chrome
Jank Busting for Better Rendering Performance
Rendering: repaint, reflow/relayout, restyle
How (not) to trigger a layout in WebKit
Web動畫性能指南 maintained by https://github.com/alexorz

Published with GitHub Pages

發佈了23 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章