所谓渲染过程就是将HTML、CSS、JavaScript转变成页面的过程~
渲染过程大致如下:
构建DOM树 》 样式计算 》 布局阶段 》 分层 》 绘制 》 分块 》 光栅化 》 合成
一、构建DOM树
将HTML转化成DOM的过程就是构建DOM树。
DOM树是存储在内存中的,便于JavaScript直接查询和修改。
二、样式计算
目的是:计算出每个DOM节点的样式,如下图所示,结果保存在computedStyle中
具体过程如下:
(1)将css转成styleSheets
目的是方便查询和修改,为样式操作提供基础~
(2)对styleSheets的样式标准化
所谓标准化就是将类似rem转成px、color转成rgb格式等
(3)计算每个DOM节点的样式,输出并保存在computedStyle中
如何计算DOM节点的样式呢?就牵扯到样式的继承规则和层叠规则
三、布局阶段
所谓布局就是计算DOM树的可见DOM节点(不包括display:none的元素、header元素)位置的过程~分为两个过程。
(1)将DOM树和computedStyle重新生成布局树(只包含可见元素),布局树的每个DOM节点都包含计算之后的样式
(2)布局计算
计算布局树节点的坐标位置~计算完成之后会把结果重新写会布局树中,所以此时布局树是包含DOM节点、computedStyle和坐标位置的结构
四、分层
渲染引擎会为特定的节点(3D转换、页面滚动、z-index、position等)生成专用的图层;
浏览器的页面实际上被分成很多图层,图层的叠加后就合成页面
哪些元素会生成图层呢?
(1)拥有层叠上下文属性(z-index、明确定位属性、拥有opacity、css滤镜filter等)的元素会被提升为图层
(2)、需要剪切clip和有滚动条的也会创建图层
最后生成图层树~
五、图层绘制
完成图层树的构建之后,渲染引擎会对图层树的每个图层进行单独绘制
渲染引擎如何绘制图层的呢? 渲染引擎实现图层的绘制会把图层的绘制拆分成很多小的绘制指令 ,在按照指令顺序组成绘制列表,就像我们们绘画的步骤一样,要按照步骤一步步完成~
六、栅格化
图层绘制输出的是绘制列表,记录了绘制顺序和绘制指令的列表,但是实际的绘制是又渲染引擎中的合成线程完成的。 当图层的绘制列表准备好之后,主线程会把该绘制列表提交(commit)给合成线程
合成线程是如何完成绘制的呢?
(1) 视口(当前可见部分)
确实没必要把页面所有的部分都绘制出来,浪费性能~ 所以合成线程会将图层划分为图快,图快的大小通常是256256或者512512;
合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。
栅格化一般会通过GPU加速生成,使用GPU生成位图的过程叫做快速栅格化或者GPU栅格化,生成的位图保存在GPU内存中~ 渲染进程把生成图块的指令发送给 GPU,然后在 GPU 中执行生成图块的位图,并保存在 GPU 的内存中。
这个阶段输出的是位图~
七 合成与显示
一旦图块光栅化之后,合成线程就会生成绘制图块的命令(DrawQuad),提交给浏览器进程
浏览器进程的viz组件,接收到合成线程发来的DrawQuad命令后,根据命令,将页面内容绘制到内存中,最后显示在屏幕上。