浏览器渲染原理
1.渲染树
DOM 树与 CSSOM 树合并后形成渲染树。
- 渲染树只包含渲染网页所需的节点。
- 布局计算每个对象的精确位置和大小。
- 最后一步是绘制,使用最终渲染树将像素渲染到屏幕上。
浏览器将 DOM 和 CSSOM 合并成一个“渲染树”,网罗网页上所有可见的 DOM 内容,以及每个节点的所有 CSSOM 样式信息。
2.渲染步骤
下面简要概述了浏览器完成的步骤:
- 处理 HTML 标记并构建 DOM 树。
- 处理 CSS 标记并构建 CSSOM 树。
- 将 DOM 与 CSSOM 合并成一个渲染树。
- 根据渲染树来布局,以计算每个节点的几何信息。
- 将各个节点绘制到屏幕上。
我们的演示网页看起来可能很简单,实际上却需要完成相当多的工作。如果 DOM 或 CSSOM 被修改,您只能再执行一遍以上所有步骤,以确定哪些像素需要在屏幕上进行重新渲染。
优化关键渲染路径就是指最大限度缩短执行上述第 1 步至第 5 步耗费的总时间。 这样一来,就能尽快将内容渲染到屏幕上,此外还能缩短首次渲染后屏幕刷新的时间,即为交互式内容实现更高的刷新率。
一般我们用JS来更新样式
比如div.style.background = ‘red’
比如div.style.display = ‘none’
比如div.classList.add (‘red’)
比如div.remove()直接删掉节点
那么这些方法有什么不同吗?
- JavaScript。一般来说,我们会使用 JavaScript 来实现一些视觉变化的效果。比如用 jQuery 的 animate 函数做一个动画、对一个数据集进行排序或者往页面里添加一些 DOM 元素等。当然,除了 JavaScript,还有其他一些常用方法也可以实现视觉变化效果,比如: CSS Animations、Transitions 和 Web Animation API。
- 样式计算。此过程是根据匹配选择器(例如 .headline 或 .nav > .nav__item)计算出哪些元素应用哪些 CSS 规则的过程。从中知道规则之后,将应用规则并计算每个元素的最终样式。
- 布局。在知道对一个元素应用哪些规则之后,浏览器即可开始计算它要占据的空间大小及其在屏幕的位置。网页的布局模式意味着一个元素可能影响其他元素,例如 元素的宽度一般会影响其子元素的宽度以及树中各处的节点,因此对于浏览器来说,布局过程是经常发生的。
- 绘制。绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。
- 合成。由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。
3.渲染方式
有三种不同的渲染方式:
1. JS / CSS > 样式 > 布局 > 绘制 > 合成
完整的像素管道
如果您修改元素的“layout”属性,也就是改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),那么浏览器将必须检查所有其他元素,然后“自动重排”页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需进行合成。
2. JS / CSS > 样式 > 绘制 > 合成
无布局的像素管道。
如果您修改“paint only”属性(例如背景图片、文字颜色或阴影等),即不会影响页面布局的属性,则浏览器会跳过布局,但仍将执行绘制。
3. JS / CSS > 样式 > 合成
无布局或绘制的像素管道。
如果您更改一个既不要布局也不要绘制的属性,则浏览器将跳到只执行合成。
这个最后的版本开销最小,最适合于应用生命周期中的高压力点,例如动画或滚动。
transform(变形)属性是实现前端动画的一个基本且重要的属性,而transition和animation和transform相配合可以使动画更加的多样化。
CSS动画知识总结
transform和它的4个属性值
1、translate(位移)
transform: translate(12px, 50%);
transform: translateX(12px);
transform: translateY(50%);
transform: translateX(-12px);
transform: translateY(-50%);
复制代码
可以在x轴y轴甚至是z轴进行位移,一般在z轴位移如果是2D的效果肉眼是难以分辨的(规律是近大远小),数值也可以是正数、负数和百分数(自身大小的百分值)。
正数是往轴的正方向移动,也就是轴的箭头指向方向,负数则相反。
这里有一个元素居中的小技巧(如下代码)
left:50%;
top:50%;
transform:translate(-50%,-50%);
复制代码
2、scale (缩放)
transform: scale(1.2);全方位
transform: scale(2, 0.5);
transform: scaleX(2);仅x轴方向
transform: scaleY(0.5);仅y轴方向
复制代码
3、rotate(旋转)默认以Z轴为基准旋转
transform: rotate3d(1, 2.0, 3.0, 10deg);3D效果
transform: rotateX(10deg);
transform: rotateY(10deg);
transform: rotateZ(10deg);
复制代码
4、skew(倾斜)
transform: skew(30deg, 1deg);
transform: skewX(30deg);
transform: skewY(1deg);
复制代码
我们需要注意的是倾斜和旋转的区别,旋转图片不会变样子,而倾斜在会让图片失去原来的样子,变得扁平化,就像口香糖一样用力拉扯它会变得很细。
transition(过渡)
顾名思义让transform在变化是有一个过度效果,不然transform就像穿越一样移动。
transition
主要包含四个属性值:
变换的属性:transition-property
,
延续的时间:transition-duration
,
在延续时间段,变换的速率变化:transition-timing-function
,
延迟时间:transition-delay
。
一般可以写成
transition:属性名、时长、过度方式、延迟
1、transition-property
(属性名)可以同时写多个属性名直接用“,”隔开。
属性名可以是:all(所有属性改变,这个常用)、opacity(透明度)、color(background-color,border-color,color等)
等等
2、transition-duration
(时长)
3、transition-timing-function
(过度方式)
a、`ease`:(逐渐变慢)默认值
b、`linear`:(匀速)
c、`ease-in`:(加速)
d、`ease-out`:(减速)
e、`ease-in-out`:(加速然后减速)
复制代码
常用的就这几个。
4、transition-delay
(延迟时间)
注意:永远不要在过渡的时候用display:none
→display:block
,
应转换成visibility:hidden
→visibility:visible
。
animation
首先声明一个关键帧(@keyframes
) – 主要作用是定义动画在不同阶段的状态。
@keyframes xxx {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
复制代码
xxx(自己随意声明)最后写在animation的属性值中(匹配)
@keyframes xxxx {
0% {}
30% {}
50% {}
70% {}
80% {}
100% {}
}
复制代码
一般有上面两种不同的写法,看个人需求来选择。
animation的属性值:时长、过度方式、延迟、次数、方向、填充模式、是否暂停、动画名(xxxx).
1、时长(s、ms等)
2、过度方式(同transition的过度方式)
3、延迟(s、ms等)
4、次数(执行几次,单程重复,加入方向才能实现往返)infinite (永不停止)
5、方向
a、normal
正常方向
b、alternate
(交替)
c、reverse
返回过来(有来有回)
d、alternate-reverse
先从终点开始,再从起点开始
6、填充模式
a、none
动画执行前后不改变任何样式
b、forwards
保持目标动画最后一帧的样式
c、backwards
保持目标动画第一帧的样式
7、是否暂停
paused
代表暂停,running
代表恢复
8、动画名 @keyframes
的名称 , 自己命名
关于面试的应答
JS优化:使用 requestAnimationFrame
代替 setTimeout
或setinterval
CSS优化:使用 will-change
或 translate