眾所周知软免,網(wǎng)頁不僅應(yīng)該被快速加載吊洼,同時還應(yīng)該流暢運(yùn)行奸远,比如快速響應(yīng)的交互磅氨,如絲般順滑的動畫……
首先我們要了解什么是 16ms 優(yōu)化
大多數(shù)設(shè)備的刷新頻率是 60 次/秒,(1000/60 = 16.6ms)也就說是瀏覽器對每一幀畫面的渲染工作要在 16ms 內(nèi)完成烦租,超出這個時間延赌,頁面的渲染就會出現(xiàn)卡頓現(xiàn)象,影響用戶體驗叉橱。
瀏覽器在一幀里面挫以,會依次執(zhí)行以下這些動作。減少或者避免 layout窃祝,paint 可以讓頁面不卡頓掐松,動畫效果更加流暢。
JavaScript:JavaScript 實現(xiàn)動畫效果粪小,DOM 元素操作等大磺。
Style(計算樣式):確定每個 DOM 元素應(yīng)該應(yīng)用什么 CSS 規(guī)則。
Layout(布局):計算每個 DOM 元素在最終屏幕上顯示的大小和位置探膊。由于 web 頁面的元素布局是相對的量没,所以其中任意一個元素的位置發(fā)生變化,都會聯(lián)動的引起其他元素發(fā)生變化突想,這個過程叫 reflow。
Paint(繪制):在多個層上繪制 DOM 元素的的文字究抓、顏色猾担、圖像、邊框和陰影等刺下。
Composite(渲染層合并):按照合理的順序合并圖層然后顯示到屏幕上绑嘹。
利用 GPU 加速優(yōu)先使用渲染層合并屬性,避免 layout橘茉,paint工腋。
從上圖可以看出姨丈,可以通過改變元素的 transform 實現(xiàn)移動,伸縮變換而非改變物體的 left擅腰,top蟋恬,width,height 避免 layout趁冈,paint歼争。讓動畫效果更加流暢。
@keyframesdemo {
? 0% {
top:10px;
? }
? 100% {
top:30px;
? }
}
優(yōu)化
@keyframesdemo {
? 0% {
transform:translateY(10px);
? }
? 100% {
transform:translateY(30px);
? }
}
二. GPU 是什么渗勘,如何用 Chrome devtools 進(jìn)行分析 debug沐绒?
獲取 DOM 并將其分割為多個層(RenderLayer)
將每個層?xùn)鸥窕梗ⅹ?dú)立的繪制進(jìn)位圖中
將這些位圖作為紋理上傳至 GPU
復(fù)合多個層來生成最終的屏幕圖像(終極 layer )乔遮。
按上面的步驟之后,即可看到
黃色邊框:有動畫 3d 變換的元素取刃,表示放到了一個新的復(fù)合層(composited layer)中渲染
藍(lán)色的柵格:這些分塊可以看作是比層更低一級的單位蹋肮,這些區(qū)域就是 RenderLayer
打開一個頁面,如果該頁面的黃色邊框很多蝉衣,那么肯定要查看一下原因了
打開 timeline 進(jìn)行錄制括尸,選中 timeline 的某一幀,然后選擇下面的 layer 病毡,可以左右拖動該模塊出現(xiàn) 3d濒翻。
我們可以看到一個頁面實際是像下面一樣組成的
從上圖不難理解,雖然我們最終在瀏覽器上看到的只是一個復(fù)印版啦膜,即最終只有一個層有送。類似于PhotoShop軟件中的“圖層”概念,最后合并所有可視圖層僧家,輸出一張圖片到屏幕上雀摘。但實際上一些dom會因為一些規(guī)則被提升成獨(dú)立的層(開啟 GPU 加速),一旦被獨(dú)立出來之后八拱,便不會再影響其他dom的布局阵赠,因為它改變之后,只是“貼上”了頁面肌稻。
目前下面這些因素都會引起Chrome創(chuàng)建合成層:
3D 或透視變換(perspective东揣,transform) CSS 屬性
使用加速視頻解碼的video元素
擁有 3D (WebGL) 上下文或加速的 2D 上下文的 canvas 元素
混合插件(如 Flash)
對自己的 opacity 做 CSS 動畫或使用一個動畫 webkit 變換的元素
擁有加速 CSS 過濾器的元素
元素A有一個 z-index 比自己小的元素B践惑,且元素B是一個合成層(換句話說就是該元素在復(fù)合層上面渲染),則元素A會提升為合成層
上面6點(diǎn)都非常容易理解嘶卧,在日常開發(fā)中尔觉,最容易出現(xiàn)問題的是第7點(diǎn)
元素A有一個 z-index 比自己小的元素B,且元素B是一個合成層(換句話說就是該元素在復(fù)合層上面渲染)
拿實際項目舉個栗子脸候,我們按照上面的步驟開啟 layer borders
尚未給上圖右手添加高層級的 z-index 時穷娱,整個頁面在移動端打開后閃退。而添加了 z-index 之后运沦,頁面正常顯示泵额,不閃退了。
仔細(xì)看上面的 gif 携添,僅僅改變了 z-index 嫁盲,就會改變大批數(shù)量的層(黃色邊框)
我們來看一個栗子烈掠,B 在做動畫羞秤,理所當(dāng)然把B提到單獨(dú)的合成層。減少重繪左敌。
按照上圖瘾蛋,我們遇到一個邏輯問題,元素B應(yīng)該在單獨(dú)的合成層上矫限,并且屏幕的最終圖像應(yīng)該在 GPU 上組成哺哼。但是A元素在B元素的頂部,我們沒有指定提升A元素自身層級的東西叼风。那么瀏覽器會做什么取董?它將強(qiáng)制為元素A創(chuàng)建一個新的合成圖層。
這樣无宿,A和B都被提升到單獨(dú)的復(fù)合層茵汰。
因此,使用 GPU 加速提升動畫性能時孽鸡,最好給當(dāng)前動畫元素增加一個高一點(diǎn)的 z-index 屬性蹂午,人為干擾復(fù)合層的排序,可以有效減少 Chrome 創(chuàng)建不必要的復(fù)合層画侣,提升渲染性能。
注意:GPU 不僅需要發(fā)送渲染層圖像到 GPU 堡妒,而且還需存儲它們溉卓,以便稍后在動畫中重用搬泥。別盲目創(chuàng)建渲染層伏尼,一定要分析其實際性能表現(xiàn)。因為創(chuàng)建渲染層是有代價的爆阶,每創(chuàng)建一個新的渲染層燥透,就意味著新的內(nèi)存分配和更復(fù)雜的層的管理辨图。對于使用移動設(shè)備的用戶來說是很坑的。移動設(shè)備沒有臺式機(jī)那么多的內(nèi)存故河。過多的 GPU 加速會引起頁面卡頓甚至閃退吱韭。
找到 layers,點(diǎn)擊當(dāng)前層鱼的,在右邊查看占用的 memory(內(nèi)存)
GPU 加速能做什么
GPU 是什么理盆,如何用 Chrome devtools 進(jìn)行分析 debug?
如何開啟 GPU 加速凑阶?
GPU 加速隱藏的坑–隱式合成