1、动画性能基础:理解浏览器渲染管线

大家好,我是你们的老朋友。今天咱们聊聊动画性能的底层逻辑。

说实话,我刚入行那会儿,觉得动画嘛,不就是改改CSS属性、调调transition?后来被一个滚动卡顿的bug折磨了三天,才意识到——不懂渲染管线,你连问题出在哪都不知道。

这一章,咱们把地基打牢。你想想看,盖楼不打地基,后面30层怎么盖?

1.1 浏览器渲染管线:页面是怎么画出来的?

浏览器把HTML/CSS变成像素,要经过五个阶段。我习惯叫它「五步走」:

  1. JavaScript:执行脚本,触发视觉变化
  2. Style:计算样式,匹配CSS选择器
  3. Layout:计算几何信息,确定每个元素的位置和大小
  4. Paint:绘制像素,填充颜色、边框、阴影
  5. Composite:合成图层,输出到屏幕

嗯,这里要注意——不是每次更新都会走完五步。具体走几步,取决于你改了什么东西。

核心结论:动画性能优化的本质,就是让浏览器走更少的步骤。

1.2 重排、重绘、合成——三兄弟的区别

这三兄弟,我一个个说清楚。

重排(Reflow)

改了什么?位置、尺寸、显示隐藏。比如改了widthheightmargindisplay: none

后果是什么?整个五步全走一遍。代价最大。

我在项目中遇到过,一个表格里动态插入行,结果整个页面都在抖。为什么?因为每一行插入都触发了全局重排。

重绘(Repaint)

改了什么?视觉外观但不影响布局。比如改了colorbackground-colorvisibility

后果是什么?跳过Layout,走Style → Paint → Composite。代价中等。

合成(Composite)

改了什么?只影响合成的属性。比如transformopacity

后果是什么?只走Composite一步。代价最小,60fps的黄金搭档。

我的经验:能用transform就别用left/top。能用opacity就别用display。这是最基础的避坑指南。

1.3 60fps目标与帧预算

为什么是60fps?因为人眼的视觉暂留效应。低于这个数,你就会觉得卡。

60fps意味着什么?每帧只有16.67ms。我算给你看:

1000ms ÷ 60帧 ≈ 16.67ms/帧

这16.67ms里,浏览器要干完所有活——JS执行、样式计算、布局、绘制、合成。留给你的时间,其实只有10ms左右。

我曾经犯过一个错:在一个滚动监听里做了大量DOM操作,结果每帧耗时超过50ms。用户滚动时就像在看幻灯片。后来我用Performance面板一查,重排占了40ms。嗯,从那以后我再也不敢在滚动回调里乱改布局了。

警告:别以为16.67ms很多。实际上,超过10ms你就该警惕了。超过16ms,卡顿是必然的。

1.4 性能分析工具概览

光说不练假把式。工具得会用。我平时最常用的三个:

工具 用途 我的用法
Chrome Performance 录制帧耗时、查看渲染流水线 先录一段,看有没有超过16ms的帧
Layers面板 查看合成层、检测层爆炸 看有没有不必要的图层
Rendering面板 实时显示FPS、绘制矩形、层边界 打开FPS Meter,边操作边看

我个人习惯,先开Rendering面板的FPS Meter,确认有没有掉帧。如果有,再用Performance面板录一段,找到罪魁祸首。

举个例子。有一次我做一个卡片翻转动画,感觉有点卡。打开FPS Meter一看,掉到40fps。录了一段Performance,发现每次翻转都触发了重排。原因是我用了rotateY但没加will-change。加上之后,直接升到60fps。

小技巧:Performance面板里,看「Summary」底部的「Rendering」耗时。如果超过5ms,说明有优化空间。

1.5 总结:记住这三句话

  • 重排最贵,重绘次之,合成最便宜。
  • 每帧只有16.67ms,别浪费在重排上。
  • 工具是眼睛,学会看Performance和FPS Meter。

好了,这一章就到这里。下一章咱们聊「硬件加速与合成层」,我会告诉你什么时候该用will-change,什么时候用了反而坏事。

公众号:蓝海资料掘金营,微信deep3321