如何實現(xiàn)動畫?
- jQuery animation:setTimeout,top/left
- animatin,transition,transform
- javascript+canvas/webGL/SVG
- requestAnimationFrame
- GPU acceleration(硬件加速)
webkit的渲染流程

webkit

分析性能
css style影響

style影響
瀏覽器渲染小結(jié)
- 渲染三個階段: Layout,Paint,Composite Layers
- 修改不同CSS屬性會觸發(fā)不同階段
- 觸發(fā)的階段越前,渲染的代價越高
硬件加速(GPU加速)
- Texture,即GPU傳輸?shù)紾PU的一個Bitmap
- GPU能快速對texture進行偏移、縮放、旋轉(zhuǎn)、修改透明度等操作

CPU vs GPU
- 相同之處:兩者都有總線和外界聯(lián)系,有自己緩存體系,以及數(shù)字和邏輯運算單元。一句話,兩者都為了完成計算任務(wù)而設(shè)計。
- 不同之處:CPU主要負責操作系統(tǒng)和應(yīng)用程序,GPU主要負責跟顯示相關(guān)的數(shù)據(jù)處理,GPU的活CPU一般都可以干,但是效率低下
Layer模型
- 瀏覽器根據(jù)CSS屬性為元素生成Layers
- 將Layers作為texture上傳到GPU
- 當改變Layer的transform,opacity屬性時,渲染會跳過Layout,paint,直接通知GPU對Layer做變換。
Layer創(chuàng)建標準
- 擁有3d transform屬性
- 使用animation,transition實現(xiàn)opacity,transform的動畫
- video
- canvas
- Flash
- 使用CSS filters的元素
- z-index大于某個相鄰節(jié)點的Layer的元素
為什么使用硬件加速快呢?
- 如果使用jquery或者js來做一個top移動100px的動畫,每次都會重主線程發(fā)傳到合成器線程
- 但是,如果用GPU transform來做的話,主線程只會傳一次到合成器線程,其余任務(wù)全部是在合成器線程,所以效率比較高。
節(jié)省了哪些時間?
- CPU進行Layout和paint的時間
- CPU向GPU傳輸位圖的時間
完美的Animation
對眼睛來說:60FPS更舒服更完美
約等于16.7ms內(nèi),我們準備好一幀的動畫
- 開始繪制的時間
- 繪制一幀的時間
- setTimeout(callback,1/60)
依靠瀏覽器內(nèi)置時鐘更新頻率,eg、IE8及以前更新間隔為15.6,setTimeout 16.7,它需要兩個15.6ms觸發(fā)。超過14.5ms,所以會出現(xiàn)丟幀的現(xiàn)象
main thread隊列 - requestAnimationFrame
- 定義繪制每一幀的工作requestAnimationFrame(callback)
- 自動調(diào)節(jié)頻率 ,callback工作太多無法再一幀內(nèi)完成,會自動降低為30fps,雖然頻率降低但比丟幀好。
Layout
觸發(fā)Layout
- 改變widht,height等和大小、位置相關(guān)的屬性
-
讀取size、positoin相關(guān)的屬性
會引起layout
盡量不觸發(fā)Layout,使用transform代替top,left的動畫。

會觸發(fā)三次layout

只觸發(fā)一次layout
但是,如果是這樣

1
我們可以這樣改

2
介紹一個庫
fastdom.js
在每一幀,先將讀操作批量運行,在批量運行寫操作
Layout小結(jié)
- 不但改變css可能導致Layout,讀取位置大小相關(guān)屬性也會導致Layout(滾動條也會導致Layout)
- 分離讀寫,減少Layout
- 面對解耦代碼,可以使用rAF推遲的方法分離讀寫
如何開發(fā)不會導致重拍
- 樣式表越簡單,重拍和重匯越快
- 重拍和重繪的DOM元素層級越高,成本就越高
- table元素的重排和重繪成本,要高于div元素
- 盡量不要把讀操作和寫操作,放在一個語句里
- 統(tǒng)一改變樣式
- 緩存重排結(jié)果
- 離線DOM Fragment/clone
- 虛擬DOM React
- 必要的時候display:none不可見元素不影響重排重繪。visibility對重排影響不影響重繪
Paint
觸發(fā)paint
- 當修改border-radius,box-shadow,color等展示相關(guān)屬性,會觸發(fā)paint
paint的代價
- continuous painting mode
- paint prefiler
- 在經(jīng)常paint的區(qū)域,要避免代價太高的style(比如不要的gif圖設(shè)置display:none)
減少不必的繪制
- gif圖即使被其他Layout蓋住不可見,也可能導致paint,不需要時應(yīng)將gif圖的display屬性設(shè)為none。輪播圖也一樣 http://jsbin.com/dizak/3/edit?html,css,output (可以用調(diào)試工具去測試性能,z-index:0,也會重排重繪,應(yīng)該直接設(shè)置display:none)
- 減少繪制區(qū)域,為引起大范圍Paint的元素生成獨立的Layout以減小Paint的范圍
Paint小結(jié)
- 簡化繪制的復雜度
- 避免不必要的繪制
- 減少繪制區(qū)域
composite Layout
- GPU也是有限度的,不要濫用GPU資源生成不必要的Layout
- 留意以外生成的Layout
