css3 動(dòng)畫給 Web 的用戶體驗(yàn)帶來(lái)了巨大提升,本文將嘗試從瀏覽器渲染的角度,來(lái)解析動(dòng)畫優(yōu)化的原理及其技巧。為大家提供一些動(dòng)畫性能優(yōu)化的參考。
目前大多數(shù)設(shè)備的屏幕刷新率為60fps(Frame per Second),即每秒60幀。因此,如果在頁(yè)面中有一個(gè)動(dòng)畫或漸變效果,或者用戶正在滾動(dòng)頁(yè)面,那么瀏覽器渲染動(dòng)畫或頁(yè)面的每一幀的速率也需要跟設(shè)備屏幕的刷新率保持一致,即每一幀要在16毫秒(1S/60 = 16.66ms)之內(nèi)完成。如果無(wú)法完成,由于幀率的下降會(huì)導(dǎo)致內(nèi)容在屏幕上抖動(dòng)。 此現(xiàn)象通常稱為卡頓,會(huì)對(duì)用戶體驗(yàn)產(chǎn)生負(fù)面影響。
在講性能之前,我們需要先對(duì)瀏覽器渲染頁(yè)面有一個(gè)基礎(chǔ)的理解。
瀏覽器在渲染一個(gè)頁(yè)面時(shí),會(huì)將頁(yè)面分為很多個(gè)圖層,圖層有大有小,每個(gè)圖層上有一個(gè)或多個(gè)節(jié)點(diǎn)。需要注意的是,如果圖層中某個(gè)元素需要重繪,那么整個(gè)圖層都需要重繪(關(guān)于重繪下面會(huì)講到)。
簡(jiǎn)單來(lái)說(shuō),瀏覽器的渲染過(guò)程其實(shí)就是將頁(yè)面轉(zhuǎn)換成像素顯示到屏幕上,大致有如下幾個(gè)步驟:
JavaScript操作: 一般來(lái)說(shuō),我們會(huì)使用 JavaScript 來(lái)實(shí)現(xiàn)一些交互操作。比如用往頁(yè)面里添加一些元素,切換顯示隱藏等
style 樣式計(jì)算: 該過(guò)程根據(jù) css 選擇器,獲取每個(gè)元素匹配的 css 樣式并計(jì)算其最終應(yīng)用樣式
Layout 布局:該過(guò)程計(jì)算元素要占據(jù)的空間大小及其在屏幕的位置。網(wǎng)頁(yè)的布局模式意味著一個(gè)元素可能影響其他元素,例如 <body> 元素的寬度一般會(huì)影響其子元素的寬度以及樹中各處的節(jié)點(diǎn),因此對(duì)于瀏覽器來(lái)說(shuō),布局是經(jīng)常發(fā)生的
Paint 繪制:本質(zhì)上就是填充像素的過(guò)程。包括繪制文字、顏色、圖像、邊框和陰影等。也就是繪制元素所有的可視效果
Composite 渲染層合并:在每個(gè)層上完成繪制過(guò)程之后,瀏覽器會(huì)將所有層按照合理的順序合并成一個(gè)圖層,然后顯示在屏幕上
如果我們需要提高動(dòng)畫的性能,需要做的就是減少瀏覽器在動(dòng)畫運(yùn)行時(shí)所需要做的工作。當(dāng) css 在進(jìn)行動(dòng)畫時(shí),其不同屬性值引起的改變,重新渲染可能會(huì)有三種執(zhí)行路徑:
A:layout -> paint -> compositeB:paint -> compositeC:composite
很明顯,最短路徑的 C 動(dòng)畫性能是最高的,所以我們?cè)谑褂脛?dòng)畫的時(shí)候就得考慮使用什么屬性,以盡量減少執(zhí)行路徑。
css 的屬性大致分為三類:布局類(layout),繪制類(paint),合成類(composite)。
由元素的布局類屬性改變所觸發(fā)的行為過(guò)程,我們稱為 reflow,也叫做 relayout(重新布局)。當(dāng)某個(gè)節(jié)點(diǎn) reflow 時(shí)會(huì)重新計(jì)算節(jié)點(diǎn)的尺寸和位置,還可能會(huì)引起其它節(jié)點(diǎn)的 reflow。
該系列屬性的改變,會(huì)執(zhí)行路徑 A 進(jìn)行重新渲染,所以性能是最差的。(這充分說(shuō)明,重排會(huì)引起重繪)
觸發(fā)重排的屬性
盒子模型相關(guān)屬性會(huì)觸發(fā)重布局:
width
height
padding
margin
display
border-width
border
min-height
定位屬性及浮動(dòng)也會(huì)觸發(fā)重布局:
top
bottom
left
right
position
float
clear
改變節(jié)點(diǎn)內(nèi)部文字結(jié)構(gòu)也會(huì)觸發(fā)重布局:
text-align
overflow-y
font-weight
overflow
font-family
line-height
vertival-align
white-space
font-size
由繪制類屬性改變觸發(fā)節(jié)點(diǎn)重新繪制其可視效果的過(guò)程,我們稱為 repaint。
該系列屬性的改變,會(huì)執(zhí)行路徑 B,所以性能一般。
觸發(fā)重繪的屬性
修改時(shí)只觸發(fā)重繪的屬性有:
color
border-style
border-radius
visibility
text-decoration
background
background-image
background-position
background-repeat
background-size
outline-color
outline
outline-style
outline-width
box-shadow
上面的屬性由于不會(huì)修改節(jié)點(diǎn)的大小和位置,因此不會(huì)觸發(fā)重排,其只是改變了節(jié)點(diǎn)內(nèi)部的渲染效果,所以只會(huì)進(jìn)行重繪以下的步驟。
目前只有兩個(gè)屬性屬于 composite 類:
transform
opactiy
該系列屬性的改變,會(huì)執(zhí)行路徑 C,所以性能最佳。
如果想了解更多 css 中會(huì)影響 Layout、Paint 和 Composite 的屬性,可參考:CSS Triggers。
pixabayhttps://www.wode007.com/sites/73237.html wallhavenhttps://www.wode007.com/sites/73236.html
減少動(dòng)畫元素,是動(dòng)畫性能優(yōu)化中首先需要完成的。通過(guò)審查頁(yè)面動(dòng)畫 DOM 元素結(jié)構(gòu),去除不必要的動(dòng)畫元素,減少元素的數(shù)量,相應(yīng)地會(huì)減少布頁(yè)面局和繪制的時(shí)間。
對(duì)于動(dòng)畫元素,盡量使用用 fixed、absolute 定位方式,避免影響到其他節(jié)點(diǎn)重排。
能用 transform、opacity 優(yōu)先使用,其屬性的改變不會(huì)發(fā)生重排和重繪。如位移操作的,可以使用translate 來(lái)實(shí)現(xiàn),漸隱漸現(xiàn)效果可以使用 opacity 屬性來(lái)實(shí)現(xiàn)。
對(duì)動(dòng)畫元素應(yīng)用transform: translate3d(0, 0, 0)、will-change: transform 等來(lái)開啟硬件加速。通常開啟硬件加速可以讓動(dòng)畫變得更加流暢。但這里需注意,在不需要的時(shí)候需去掉避免過(guò)多的內(nèi)存消耗。
transform: translate3d(0, 0, 0);transform: translateZ(0);will-change: transform
聯(lián)系客服