衆所周知,網頁不僅應該被快速加載,同時還應該流暢運作,比如快速響應的互動,如絲般順滑的動畫……
首先我們要了解什麼是 16ms 優化
大多數裝置的重新整理頻率是 60 次/秒,(1000/60 = 16.6ms)也就說是浏覽器對每一幀畫面的渲染工作要在 16ms 内完成,超出這個時間,頁面的渲染就會出現卡頓現象,影響使用者體驗。
浏覽器在一幀裡面,會依次執行以下這些動作。減少或者避免 layout,paint 可以讓頁面不卡頓,動畫效果更加流暢。
1. javascript:javascript 實作動畫效果,dom 元素操作等。
2. style(計算樣式):确定每個 dom 元素應該應用什麼 css 規則。
3. layout(布局):計算每個 dom 元素在最終螢幕上顯示的大小和位置。由于 web 頁面的元素布局是相對的,是以其中任意一個元素的位置發生變化,都會關聯的引起其他元素發生變化,這個過程叫 reflow。
4. paint(繪制):在多個層上繪制 dom 元素的的文字、顔色、圖像、邊框和陰影等。
5. composite(渲染層合并):按照合理的順序合并圖層然後顯示到螢幕上。
利用 gpu 加速優先使用渲染層合并屬性,避免 layout,paint。
從上圖可以看出,可以通過改變元素的 transform 實作移動,伸縮變換而非改變物體的 left,top,width,height 避免 layout,paint。讓動畫效果更加流暢。
優化
浏覽器渲染一個頁面大緻是按照下面這個步驟執行。
1. 擷取 dom 并将其分割為多個層(renderlayer) 2. 将每個層栅格化,并獨立的繪制進位圖中 3. 将這些位圖作為紋理上傳至 gpu 4. 複合多個層來生成最終的螢幕圖像(終極 layer )。
chrome 開啟檢視 renderlayer
按上面的步驟之後,即可看到
1. 黃色邊框:有動畫 3d 變換的元素,表示放到了一個新的複合層(composited layer)中渲染
2. 藍色的栅格:這些分塊可以看作是比層更低一級的機關,這些區域就是 renderlayer
打開一個頁面,如果該頁面的黃色邊框很多,那麼肯定要檢視一下原因了
chrome 檢視 layer
打開 timeline 進行錄制,選中 timeline 的某一幀,然後選擇下面的 layer ,可以左右拖動該子產品出現 3d。
我們可以看到一個頁面實際是像下面一樣組成的
從上圖不難了解,雖然我們最終在浏覽器上看到的隻是一個影印版,即最終隻有一個層。類似于photoshop軟體中的“圖層”概念,最後合并所有可視圖層,輸出一張圖檔到螢幕上。但實際上一些dom會因為一些規則被提升成獨立的層(開啟 gpu 加速),一旦被獨立出來之後,便不會再影響其他dom的布局,因為它改變之後,隻是“貼上”了頁面。
根據這個優點,我們可以把頁面中一些布局經常變換的dom(動畫)提升到獨立的層。那麼,浏覽器在之後的 16ms 中,隻需進行下面的幾個步驟。
目前下面這些因素都會引起chrome建立合成層:
1. 3d 或透視變換(perspective,transform) css 屬性 2. 使用加速視訊解碼的video元素 3. 擁有 3d (webgl) 上下文或加速的 2d 上下文的 canvas 元素 4. 混合插件(如 flash) 5. 對自己的 opacity 做 css 動畫或使用一個動畫 webkit 變換的元素 6. 擁有加速 css 過濾器的元素 7. 元素a有一個 z-index 比自己小的元素b,且元素b是一個合成層(換句話說就是該元素在複合層上面渲染),則元素a會提升為合成層。
上面7點都非常容易了解,在日常開發中,最容易出現問題的是第7點
元素a有一個 z-index 比自己小的元素b,且元素b是一個合成層(換句話說就是該元素在複合層上面渲染)
拿實際項目舉個栗子,我們按照上面的步驟開啟 layer borders
尚未給上圖右手添加高層級的 z-index 時,整個頁面在移動端打開後閃退。而添加了 z-index 之後,頁面正常顯示,不閃退了。
仔細看上面的 gif ,僅僅改變了 z-index ,就會改變大批數量的層(黃色邊框)
為什麼 z-index 力量這麼大?
我們來看一個栗子,b 在做動畫,理所當然把b提到單獨的合成層。減少重繪。
按照上圖,我們遇到一個邏輯問題,元素b應該在單獨的合成層上,并且螢幕的最終圖像應該在 gpu 上組成。但是a元素在b元素的頂部,我們沒有指定提升a元素自身層級的東西。那麼浏覽器會做什麼?它将強制為元素a建立一個新的合成圖層。
這樣,a和b都被提升到單獨的複合層。
是以,使用 gpu 加速提升動畫性能時,最好給目前動畫元素增加一個高一點的 z-index 屬性,人為幹擾複合層的排序,可以有效減少 chrome 建立不必要的複合層,提升渲染性能。
注意:gpu 不僅需要發送渲染層圖像到 gpu ,而且還需存儲它們,以便稍後在動畫中重用。别盲目建立渲染層,一定要分析其實際性能表現。因為建立渲染層是有代價的,每建立一個新的渲染層,就意味着新的記憶體配置設定和更複雜的層的管理。對于使用移動裝置的使用者來說是很坑的。移動裝置沒有桌上型電腦那麼多的記憶體。過多的 gpu 加速會引起頁面卡頓甚至閃退。
找到 layers,點選目前層,在右邊檢視占用的 memory(記憶體)
整篇文章介紹了下面幾個部分
● gpu 加速能做什麼 ● gpu 是什麼,如何用 chrome devtools 進行分析 debug? ● 如何開啟 gpu 加速? ● gpu 加速隐藏的坑–隐式合成
參考:
本文作者:ai研習社