一、回顾
大致梳理一下前面四篇文章主要讲的内容。
- 把
URL
变成字符流 - 把字符流变成词(
token
)流 - 把词(
token
)流构造成DOM
树 - 把不含样式信息的
DOM
树应用CSS
规则,变成包含样式信息的DOM
树 - 并且根据样式信息,计算了每个元素的位置和大小。
二、概括
本文是最后的步骤,就是根据这些样式信息和大小信息,为每个元素在内存中渲染它的图形,并且把它绘制到对应的位置。
三、渲染
本文中出现的“渲染”一词,统一指的是它在图形学的意义,也就是把模型变成位图的过程。
3.1、位图
在内存里建立一张二维表格,把一张图片的每个像素对应的颜色保存进去。
位图信息也是 DOM
树中占据浏览器内存最多的信息,做内存占用优化时,主要就是考虑这一部分。
3.2、图形和文字
浏览器中渲染这个过程,就是把每一个元素对应的盒变成位图。这里的元素包括
HTML
元素和伪元素,一个元素可能对应多个盒(比如inline
元素,可能会分成多行)。每一个盒对应着一张位图。
- 盒的背景、边框、SVG 元素、阴影等特性,都是需要绘制的图形类。
- 盒中的文字,也需要用底层库来支持,叫做字体库。能根据字符的码点抽取出字形。字形分为像素字形和矢量字形两种。
四、合成
合成的过程,就是为一些元素创建一个“合成后的位图”(称为合成层),把一部分子元素渲染到合成的位图上面。
1、好的合成策略是“猜测”可能变化的元素,把它排除到合成之外。
举个例子:
<div id="a"> <div id="b">...</div> <div id="c" style="transform:translate(0,0)"></div> </div>
假设合成策略能够把 a、b
两个 div
合成,而不把 c
合成,执行以下代码时:
document.getElementById("c").style.transform = "translate(100px, 0)";
绘制的时候,只需要绘制 a 和 b 合成好的位图和 c,从而减少了绘制次数。如果 b 有很多复杂的子元素,那么性能提升收益非常高。
2、主流浏览器一般根据 position、transform 等属性来决定合成策略,新的 CSS 标准中,规定了 will-change 属性,提升合成策略的效果。
五、绘制
把任何位图合成到
最终位图
的操作称为绘制。
1、绘制
发生的频率比我们想象中要高得多。
比如:鼠标的每次移动,都造成了重新绘制,如果我们不重新绘制,就会产生大量的鼠标残影。
2、计算机图形学中,使用的方案就是脏矩形
算法限制绘制面积,也就是把屏幕均匀地分成若干矩形区域。