文章目錄
- JS影片
- CSS3影片
- 瀏覽器的渲染流程
- 回流(重排) 和 重繪
JS影片
JS影片:也被稱為 逐幀影片,在時間幀上繪制內容,一幀一幀的,所以它的可再造性很高,幾乎可以完成任何想要的影片形式,
缺點:
- 有可能造成丟幀的情況,JavaScript在瀏覽器的主執行緒中運行,而主執行緒中還有其它需要運行的JavaScript腳本、樣式計算、布局、繪制任務等,對其干擾導致執行緒可能出現阻塞,從而造成丟幀,
- 代碼的復雜度高于CSS影片,
優點:
- JavaScript影片控制能力很強,可以在影片播放程序中對影片進行控制:開始、暫停、回放、終止、取消都是可以做到的,
- 影片效果比css3影片豐富,有些影片效果,比如曲線運動、沖擊閃爍、視差滾動效果,只有JavaScript影片才能完成,
- CSS3有兼容性問題,而JS大多時候沒有兼容性問題,
CSS3影片
CSS3影片:也被稱為 補間影片,原因是只需要添加關鍵幀的位置,其他的未定義的幀會被自動生成
缺點:
- 運行程序控制較弱,無法附加事件系結回呼函式,CSS影片只能暫停,不能在影片中尋找一個特定的時間點,不能在半路反轉影片,不能變換時間尺度,不能在特定的位置添加回呼函式或是系結回放事件,無進度報告
- 代碼冗長,想用 CSS 實作稍微復雜一點影片,最后CSS代碼都會變得非常笨重,
優點:
-
瀏覽器可以對影片進行優化,
- 瀏覽器使用與 requestAnimationFrame類似的機制,requestAnimationFrame比起setTimeout,setInterval設定影片的優勢主要是:
- requestAnimationFrame會把每一幀中的所有DOM操作集中起來,在一次重繪或回流中就完成,并且重繪或回流的時間間隔緊緊跟隨瀏覽器的重繪頻率,一般來說,這個頻率為每秒60幀,
- 在隱藏或不可見的元素中requestAnimationFrame不會進行重繪或回流,這當然就意味著更少的cpu,gpu和記憶體使用量,
- 強制使用硬體加速 (通過 GPU 來提高影片性能)
- 瀏覽器使用與 requestAnimationFrame類似的機制,requestAnimationFrame比起setTimeout,setInterval設定影片的優勢主要是:
-
代碼相對簡單,性能調優方向固定
-
對于幀速表現不好的低版本瀏覽器,CSS3可以做到自然降級,而JS則需要撰寫額外代碼
總結:
- 如果影片只是一些簡單的狀態切換,滑動等效果,不需要中間的控制程序,CSS33是比較好的選擇,它直接在CSS檔案中就可以實作,并不需要引入太多的JS庫,
- 而想做一些復雜的客戶端界面,開發一個復雜 UI的App,實作一個復雜紋理影片等,需要對頁面進行精準的控制計算,應該使用JS影片,這樣影片可以保持高效,并且作業流也更可控,
因此,在實作一些小的互動動效的時候,就多考慮考慮CSS影片,對于一些復雜控制的影片,使用javascript比較可靠,
瀏覽器的渲染流程
- 決議 HTML 生成DOM 樹
- 決議 CSS 樣式生成 CSSOM 樹,CSSOM 樹與 DOM 樹結合生成 Render 樹
- 布局 Render 樹 對每個節點進行布局處理,確定在螢屏上的位置
- 繪制 Render 樹,遍歷渲染樹將每個節點繪制出來
注意:為了優化用戶體驗,渲染引擎不會等到 HTML 決議完才創建布局渲染樹
1、生成 DOM 樹
- DOM 樹的構建是一個深度遍歷程序,也就是說只有在所有子節點都構建好后才會去構建當前節點的下一個兄弟節點
2、生成 Render 樹
- 生成 DOM 樹的同時會生成 CSSOM 樹,根據 CSSOM 和 DOM 樹構建 Render 樹,渲染樹包括顏色,尺寸等顯示屬性的矩形
DOM 樹 和Render 樹 對應關系如下圖:

回流(重排) 和 重繪
1、回流 (Reflow) (重排):
當Render Tree中 部分或全部元素的 尺寸、結構、或某些屬性 (例如:幾何屬性:display、float、grid、width、padding等)發生改變時,影響了該節點的幾何屬性,導致該節點位置發生變化,觸發瀏覽器重新渲染部分或全部檔案的程序稱為回流,
渲染樹的節點發生改變,影響了該節點的幾何屬性,,此時就會觸發瀏覽器回流并重新生成渲染樹,
會導致回流的操作:
- 頁面首次渲染
- 瀏覽器視窗大小發生改變
- 元素尺寸或位置發生改變
- 元素內容變化(文字數量或圖片大小等等)
- 元素字體大小變化
- 添加或者洗掉可見的DOM元素
- 激活CSS偽類(例如::hover)
- 查詢某些屬性或呼叫某些方法
一些常用且會導致回流的屬性和方法:
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- scrollIntoView()、scrollIntoViewIfNeeded() getComputedStyle()
- getBoundingClientRect()
- scrollTo()
2、重繪 (Repaint):
當頁面中元素樣式的改變并不影響它在檔案流中的位置時(例如:外觀屬性:color、background-color、visibility、text等),瀏覽器會將新樣式賦予給元素并重新繪制它,這個程序稱為重繪,
相比于回流,重繪的作用不會那么強烈,
渲染樹的節點發生改變,但不影響該節點的幾何屬性,并且回流對瀏覽器性能的消耗是遠大于重繪的,
注意:回流必將引起重繪,重繪不一定會引起回流,
3、性能影響:
有時即使僅僅回流一個單一的元素,它的父元素以及任何跟隨它的元素也會產生回流,
現代瀏覽器會對頻繁的回流或重繪操作進行優化:
瀏覽器會維護一個佇列,把所有引起回流和重繪的操作放入佇列中,如果佇列中的任務數量或者時間間隔達到一個閾值的,瀏覽器就會將佇列清空,進行一次批處理,這樣可以把多次回流和重繪變成一次,
當訪問以下 屬性或方法 時,瀏覽器會立刻清空佇列:
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- width、height
- getComputedStyle()
- getBoundingClientRect()
因為佇列中可能會有影響到這些屬性或方法回傳值的操作,即使希望獲取的資訊與佇列中操作引發的改變無關,瀏覽器也會強行清空佇列,確保拿到的值是最精確的,
4、避免回流和重繪:
CSS:
- 避免使用table布局,
- 盡可能在DOM樹的最末端改變class,
- 避免設定多層行內樣式,
- 將影片效果應用到position屬性為absolute或fixed的元素上,
- 避免使用CSS運算式(例如:calc()),
JavaScript:
- 避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式串列定義為class并一次性更改class屬性,
- 避免頻繁操作DOM,創建一個documentFragment,在它上面應用所有DOM操作,最后再把它添加到檔案中,
- 也可以先為元素設定display:none,操作結束后再把它顯示出來,因為在display屬性為none的元素上進行的DOM操作不會引發回流和重繪,
- 避免頻繁讀取會引發回流 / 重繪的屬性,如果確實需要多次使用,就用一個變數快取起來,
- 對具有復雜影片的元素使用絕對定位,使它脫離檔案流,否則會引起父元素及后續元素頻繁回流,
參考優秀文章:
為什么 CSS 影片比 JavaScript 高效?
瀏覽器的回流與重繪 (Reflow & Repaint)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/357133.html
標籤:其他
