Published on

浏览器渲染帧

Authors
  • avatar
    Name
    叫我小N就好啦
    GitHub
    @MinorN

浏览器渲染帧

理解渲染帧

如果你打游戏的话,那么帧这个词肯定不默认,常说帧数太低了,太卡了,那么帧数到底是什么呢?

手机、电脑默认的刷新频率都是 60FPS,也就是 1s 内渲染 60 次,大概就是 16.7ms 渲染一次,这 16.7ms 也就叫做一帧,也就是说,我们的操作如果在一帧内完成并渲染,那么页面就会很流畅,没有卡顿感,反之,就会产生卡的感觉,影响用户的体验,当然,帧数越高,画面显示就越流畅

在浏览器里面,一个标准帧是 16.7ms,在这个标准帧里面,浏览器需要完成主线程操作并且 commit 给 Compositor 进程(合成)

如此来看,丢帧也就是主线程中操作太多,耗时长,导致 commit 操作被推迟,浏览器不能够即使将页面渲染到屏幕上,从而导致丢帧

在浏览器的一个渲染帧里,会有一段空闲时间,如果操作小于 16.7ms,那么在这一帧里面就会存在空闲时间,就可以利用这段空闲时间来做一些耗时的任务(requestIdleCallback

接下来我们使用 Performance 来检测帧数,打开官网示例,打开 F12,按下 ctrl + shift + p 搜索 fps

左上角就会出现 FPS,我们多加点小球,然后在 Performance 面板开始录制(录制几秒即可)

可以明显的看到页面的帧数已经大幅度降低,所以说肯定是渲染出现了问题

注意 Frames,绿色表示正常,黄色则表示丢帧(我这里显示 7ms 是因为帧数是 144)

所以可以锁定频繁回流重绘会导致页面卡顿

进入源码后可以看到读取 offsetTop 触发了回流重绘(循环,不断读取 offetTop)

频繁的回流重绘导致卡顿

我们经常听到一句话:频繁的回流重绘会导致页面卡顿,那么为什么会导致卡顿呢?

  1. 计算复杂,由于回流涉及到元素的位置等属性的重新计算,很可能遍历整个 DOM 数,越大越复杂的项目上面尤为明显
  2. 渲染的停顿,发生回流时,浏览器可能需要停止渲染,重新计算布局,然后再绘制,所以可能导致页面卡顿、闪烁
  3. 频繁触发,上述案例中,我们需要用到 offsetTop 属性,所以会一直触发读取,由于 offsetTop 需要回流重新计算,所以导致页面卡顿

那么我们知道是 offsetTop 的问题,那么不用这个属性就可以了,直接用 style.top 就行(这两个属性有区别)

offsetTop 和 style.top 的区别

  • offsetTop:是一个只读的属性,用来获取元素相对于其包含元素的顶部偏移量,访问它的时候会触发浏览器重新计算布局,因为必须保证这个值是最新的
  • style.top:是一个样式属性,代表元素的 top 值,不会触发重排、强制同步,所以不需要重新计算页面布局