HTML5 Canvas Konva 全部性能技巧列表
不想把时间花在性能问题上?申请性能评审。
为什么这很重要
HTML5 Canvas 可以高效完成绘制工作,Konva 内部也有许多用于提高性能的功能。但是,随着项目复杂度增加或舞台上的图形数量增多,性能必然会受到影响。
优化目标
这里的优化主要遵循两条通用规则:
-
尽量减少计算:所有计算都需要时间。单次计算可能只需极短时间,但你的代码、Konva、JavaScript 和更底层代码产生的数千或数百万次计算会不断累积。如果原本流畅的动画或效果出现卡顿,人眼就能察觉这种影响。
-
尽量减少绘制:所有绘制都有性能成本,因此这条规则很重要。成本分为两类:一类是上一点介绍的绘制计算,另一类是将绘制内容从内存传输到 屏幕。某些情况下,还会有中间的离屏合成或逐像素处理。因此,请尽量减少绘制。
舞台
-
优化舞台尺寸——按照“尽量减少绘制”的规则,请避免创建大型舞台。将大量字节从内存传输到屏幕会降低性能。此处提供了一些解决超大舞台问题的替代方法。
-
在移动端设置视口——缩放图像会明显降低性能。因此,请为移动端应用设置视口:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">。这样可以避免对 Konva 输出进行不必要的缩放。 -
在 Retina 设备上使用
Konva.pixelRatio = 1——Konva 会自动调整像素比,从而在所有设备上清晰渲染。如果 Retina 设备的性能不佳,请设置Konva.pixelRatio = 1,以减少 Konva 的缩放工作。在某些情况下,此设置可能影响输出,因此请确认结果质量符合要求。
图层
-
图层管理——在内部,每个 Konva 图层都是一个单独的 HTML5 Canvas 元素。这样可以只刷新发生变化的图层,从而避免刷新整个舞台的性能成本。但是,每个图层都会增加性能开销,因此应尽量减少图层数量。
-
使用
layer.listening(false)——Konva 为绘制的所有图形提供鼠标和触摸事件监听器。每个监听器都有性能成本。对于包含许多图 形的图层,Konva 必须花费大量周期检查可能触发的监听器。如果图层中的所有图形都不需要响应事件,请设置layer.listening(false)以消除此开销。请参阅示例。图形部分也有类似技巧。 -
优化拖动成本——在图层上拖动图形时,每次移动事件循环都必须重绘该图层。为避免此性能成本,请在拖动时将图形移动到专用图层,并在拖动结束时将其移回原图层。请参阅示例
图形
-
图形缓存——Konva 在内部创建图形的图像,并在需要绘制图形时使用该图像。绘制图像可以避免按照绘制指令组合图形的开销,并能明显提高复杂图形和组的性能。
-
整理图形——舞台中的每个图形都会产生存在成本。要优化性能,请隐藏或从图层中移除不可见、不透明度为 0 或移出视野的对象。
-
使用
shape.listening(false)——与图层一样(请参阅上文第 7 点),Konva 会检查何时应为图形触发事件,这会产生性能成本。让图形停止监听事件可以降低此成本,详情请参阅禁用监听。 -
禁用完美绘制——在某些情况下,HTML5 Canvas 的绘制结果可能与预期不同。有关示例,请参阅禁用完美绘制。Konva 使用完美绘制功能执行额外工作以修正结果,但这会产生性能成本。当图形同时具有填充、描边和不透明度时, 设置
shape.perfectDrawEnabled(false)可以避免此成本,并且不会降低输出质量。 -
优化描边绘制——当图形同时具有描边和阴影时,Konva 会执行一次额外的内部绘制,以获得符合预期的结果。禁用 Konva 为描边添加的阴影,可以避免此性能负担。
动画
- 优化动画——避免为两次视觉变化之间的动画步骤执行不必要的重绘。
内存
- 避免内存泄漏——Konva 会处理许多可能产生内存泄漏的情况,但你仍需正确创建和移除图形与补间。
以下示例展示了其中一些性能技巧的实际效果:
- Vanilla
- React
- Vue