從重繪重排角度講解transform的動畫性能

render樹的構建

瀏覽器取回代碼後,首先會構造DOM樹,根據HTML標籤,構造DOM樹。php

以後會解析CSS樣式,解析的順序是瀏覽器的樣式 -> 用戶自定義的樣式 -> 頁面的link標籤等引進來的樣式 -> 寫在style標籤裏面的內聯樣式html

最後根據DOM樹以及解析的CSS樣式,構造RENDER樹,在RENDER樹中,會把DOM樹中沒有的元素給去除,好比head標籤以及裏面的內容,以及display:none的元素也會被去除。html5

一旦RENDER樹構建完成,瀏覽器會把樹裏面的內容繪製在屏幕上。node

<html>
<head>
  <title>Beautiful page</title>
</head>
<body>
    
  <p>
    Once upon a time there was 
    a looong paragraph...
  </p>
  
  <div style="display: none">
    Secret message
  </div>
  
  <div><img src="..." /></div>
  ...
 
</body>
</html>

構造的DOM樹以下瀏覽器

documentElement (html)
    head
        title
    body
        p
            [text node]
        
        div 
            [text node]
        
        div
            img
        
        ...

RENDER樹以下佈局

root (RenderView)
    body
        p
            line 1
        line 2
        line 3
        ...
        
    div
        img
        
    ...

重繪(repaint)和重排(reflow)

當DOM的變化影響了元素的幾何屬性(寬或高),瀏覽器須要從新計算元素的幾何屬性,一樣其餘元素的幾何屬性和位置也會所以受到影響。瀏覽器會使渲染樹中受到影響的部分失效,並從新構造渲染樹。這個過程稱爲重排。完成重排後,瀏覽器會從新繪製受影響的部分到屏幕,該過程稱爲重繪。並非全部的DOM變化都會影響幾何屬性,好比改變一個元素的背景色並不會影響元素的寬和高,這種狀況下只會發生重繪。性能

重排必然致使重繪,因此重排更加噁心。其實咱們一直研究的應該是怎麼避免觸發屢次重排。優化

重排什麼時候發生

添加或者刪除可見的DOM元素
元素位置改變
元素尺寸改變
元素內容改變(例如:一個文本被另外一個不一樣尺寸的圖片替代)
頁面渲染初始化(這個沒法避免)
瀏覽器窗口尺寸改變

瀏覽器的自動優化

var ele = document.getElementById('myDiv');
ele.style.borderLeft = '1px';
ele.style.borderRight = '2px';
ele.style.padding = '5px';

乍一想,元素的樣式改變了三次,每次改變都會引發重排和重繪,因此總共有三次重排重繪過程,可是瀏覽器並不會這麼笨,它會把三次修改「保存」起來(大多數瀏覽器經過隊列化修改並批量執行來優化重排過程),一次完成!可是,有些時候你可能會(常常是不知不覺)強制刷新隊列並要求計劃任務當即執行。獲取佈局信息的操做會致使隊列刷新,好比:動畫

offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop, scrollLeft, scrollWidth, scrollHeight
clientTop, clientLeft, clientWidth, clientHeight
getComputedStyle() (currentStyle in IE)

所以,儘可能不要在修改樣式或者佈局信息時查詢樣式,由於查詢的時候會強制重排,致使瀏覽器沒法優化屢次重排。spa


使用絕對位置定位頁面上的動畫元素,將其脫離文檔流,能夠有效的防止重排。好比有時候作動畫特效時,咱們經過設置position:absolute能夠有效的減小重排。這讓我想到,之前作動畫的時候經過修改margin-left屬性而不是left屬性絕對是一個很很差的作法。

transform是否能夠避免重排重繪問題

那麼使用CSS3的transform來實現動畫是否能夠避免重排問題?或者說瀏覽器針對這一部分作了其餘優化?

通過一番查找,答案以下:

CSS的最終表現分爲如下四步:Recalculate Style -> Layout -> Paint Setup and Paint -> Composite Layers

按照中文的意思大體是 查找並計算樣式 -> 排布 -> 繪製 -> 組合層

這上面的幾個步驟有點相似於上文說到的重排一定致使重繪,而查詢屬性會強制發生重排。因此上文提到的重排重繪內容能夠結合這裏進行理解。

因爲transform是位於Composite Layers層,而widthleftmargin等則是位於Layout層,在Layout層發生的改變一定致使Paint Setup and Paint -> Composite Layers,因此相對而言使用transform實現的動畫效果確定比left這些更加流暢。

並且就算拋開這一角度,在另外一方面瀏覽器也會針對transform等開啓GPU加速。

參考文章

https://www.html5rocks.com/en...

http://www.phpied.com/renderi...

http://www.cnblogs.com/zichi/...

寫完文章後又從新查了一下關於CSS3動畫性能方面的文章,發現大漠老師寫的這篇很不錯,並且跟本身理解的觀點有部分類似,先放上來,以後再認真看。

https://www.w3cplus.com/anima...

相關文章
相關標籤/搜索