5-渲染樹-佈局和繪製
renderer 節點剛剛建立,插入 render tree 中並沒有 position 和 size 資訊,而 layout 階段就是計算元素幾何資訊的地方。因為瀏覽器採用的是流式佈局,計算元素的幾何資訊是一次性的,而且後面元素幾乎不影響前面元素的幾何資訊,除 table 元素例外。
每一個 renderer 都要一個 layout 方法,而整個過程是從 render 樹的底層節點開始,遞迴的計算每一個節點的幾何資訊,root renderer 的位置是瀏覽器視窗的左上角,而對應的大小就是瀏覽器視窗的大小。
佈局也有不同的種類:全域性佈局和增量佈局。
全部的樣式改變,影響到所有的 renderer (如 font-size)或是調整了視窗的大小(resize),會觸發全域性佈局。而如果僅僅是 renderer 的位置改變的時候,整個解析器並不會再次渲染 renderer 大小而是去快取中取。
而有 renderer 標記為 dirty 時,會觸發增量佈局,該過程是非同步的。標記 dirty 是作用就是標記自身,告訴解析器說:「我需要重新layout了。」
計算完對應的佈局之後,開始就是 painting 階段,同樣遍歷 render tree,讓每一個節點觸發自身的 paint 函式,然後使用 UI infrastructure component 去繪製整個頁面。每一個元素繪製的順序是背景顏色、背景圖片、邊框、children、outline。而我們知道一般在後續的解析指令碼中,可能會觸發重繪,而繪製遵行的原則是:當樣式發生變化時,瀏覽器會盡可能做出最小的響應。
繪製的過程有所講究的:很早之前(chrome最開始的版本),繪製過程是將 render tree 的資訊轉化為視窗上的每一個畫素點,這個過程叫做光柵化(rasterizing),其實叫做柵格化比較好理解。但這樣僅僅繪製的是當前視窗的影像,當視窗移動的時候,才會將尚未繪製的部分進行刪格化。
但現今瀏覽器更多采用的是 複合層(compositing)方式,而改方式其實就是將一個頁面分為不同的 layer,順便刪格化這些 layer,而展示方式變為將不同的 layer 合併為一個新的畫面,這樣呈現給 web 動畫創造了良好的基礎。
通過以上這麼多的流程,最後就是讓你我看到了,設計師和工程師們辛苦的傑作咯~