動(dòng)畫(huà)卡頓是在移動(dòng)web開(kāi)發(fā)時(shí)經(jīng)常遇到的問(wèn)題,解決這個(gè)問(wèn)題一般會(huì)用到css3硬件加速。
css3硬件加速這個(gè)名字感覺(jué)上很高大上,其實(shí)它做的事情可以簡(jiǎn)單概括為:通過(guò)GPU進(jìn)行渲染,解放cpu。
現(xiàn)象
通過(guò)對(duì)比不使用css3加速和使用css3加速兩個(gè)例子,我們可以看到兩者渲染的差異:


前者通過(guò)改變top和left屬性進(jìn)行動(dòng)畫(huà),fps維持在47左右,cpu一直進(jìn)行計(jì)算;后者通過(guò)transform實(shí)現(xiàn),fps在62左右,cpu基本不需要計(jì)算。對(duì)比可知通過(guò)transform不僅提升了渲染性能,也解放了cpu。
原理
DOM樹(shù)和CSS結(jié)合后形成渲染樹(shù)。渲染樹(shù)中包含了大量的渲染元素,每一個(gè)渲染元素會(huì)被分到一個(gè)圖層中,每個(gè)圖層又會(huì)被加載到GPU形成渲染紋理。GPU中transform是不會(huì)觸發(fā) repaint 的,這一點(diǎn)非常類(lèi)似3D繪圖功能,最終這些使用 transform的圖層都會(huì)由獨(dú)立的合成器進(jìn)程進(jìn)行處理。
通過(guò)chrome的timeline工具,綠色框代表需要repaint的部分,橙色框代表渲染圖層,對(duì)比兩者可知采用的css3硬件加速后,不會(huì)進(jìn)行repaint操作,而只會(huì)產(chǎn)生一個(gè)渲染圖層,GPU就負(fù)責(zé)操作這個(gè)渲染圖層。


復(fù)合圖層
在原理中我們提到transform會(huì)創(chuàng)建一個(gè)圖層,GPU會(huì)來(lái)執(zhí)行transform的操作,這個(gè)圖層且稱(chēng)為復(fù)合圖層(composited layer)。
雖然 Chrome 的啟發(fā)式方法(heuristic)隨著時(shí)間在不斷發(fā)展進(jìn)步,但是從目前來(lái)說(shuō),滿(mǎn)足以下任意情況便會(huì)創(chuàng)建層:
- 3D 或透視變換(perspective transform) CSS 屬性
- 使用加速視頻解碼的元素,如<video>
- 擁有 3D (WebGL) 上下文或加速的 2D 上下文的元素,如<canvas>
- 混合插件(如 Flash)
- 對(duì)自己的 opacity 做 CSS 動(dòng)畫(huà)或使用一個(gè)動(dòng)畫(huà) webkit 變換的元素
- 擁有加速 CSS 過(guò)濾器的元素,如CSS filters
- 元素有一個(gè)包含復(fù)合層的后代節(jié)點(diǎn)(換句話(huà)說(shuō),就是一個(gè)元素?fù)碛幸粋€(gè)子元素,該子元素在自己的層里)
- 元素有一個(gè) z-index 較低且包含一個(gè)復(fù)合層的兄弟元素(換句話(huà)說(shuō)就是該元素在復(fù)合層上面渲染)
如果頁(yè)面建立了過(guò)多的復(fù)合圖層,同樣也會(huì)造成頁(yè)面的卡頓。在CSS3硬件加速也有坑這篇文章中,作者介紹了由于z-index造成復(fù)合圖層過(guò)多而引發(fā)的問(wèn)題,在以后開(kāi)發(fā)時(shí)可以借鑒??梢哉{(diào)試圖層過(guò)多卡頓頁(yè)面了解z-idnex對(duì)圖層創(chuàng)建的影響。
啟用
如下幾個(gè)css屬性可以觸發(fā)硬件加速:
- transform
- opacity
- filter
- will-change:哪一個(gè)屬性即將發(fā)生變化,進(jìn)而進(jìn)行優(yōu)化。
上面的的例子中用到的是transform 2D,它是在運(yùn)行時(shí)才會(huì)創(chuàng)建圖層,因此在動(dòng)畫(huà)開(kāi)始和結(jié)束時(shí)會(huì)進(jìn)行repaint操作;而瀏覽器在渲染前就為transform 3D創(chuàng)建了圖層。


可以通過(guò)transform的3D屬性強(qiáng)制開(kāi)啟GPU加速:
transform: translateZ(0);
transform: rotateZ(360deg);
注意事項(xiàng)
- 不能讓每個(gè)元素都啟用硬件加速,這樣會(huì)暫用很大的內(nèi)存,使頁(yè)面會(huì)有很強(qiáng)的卡頓感。
- GPU渲染會(huì)影響字體的抗鋸齒效果。這是因?yàn)镚PU和CPU具有不同的渲染機(jī)制,即使最終硬件加速停止了,文本還是會(huì)在動(dòng)畫(huà)期間顯示得很模糊。
參考文章:
- CSS動(dòng)畫(huà)之硬件加速:作者比較詳細(xì)介紹了硬件加速,總結(jié)的很到位。
- CSS3硬件加速也有坑: 作者介紹了由于z-index造成復(fù)合圖層過(guò)多,以后開(kāi)發(fā)加以注意。
- 使用CSS3 will-change提高頁(yè)面滾動(dòng)、動(dòng)畫(huà)等渲染性能: will-change的介紹
- javascript性能優(yōu)化-repaint和reflow:性能殺手以及優(yōu)化方法。
- 兩張圖解釋CSS動(dòng)畫(huà)的性能:比較詳細(xì)對(duì)比了采用硬件加速和不采用硬件加速的流程差異。