Skip to main content

使用 Konva 提升 HTML5 Canvas 性能

Canvas 性能取决于场景复杂度、重绘频率、像素数量和命中检测。应优化经过测量的限制因素,而不只是节点数量。

在具有代表性的设备上使用浏览器性能工具。针对真实场景记录帧时间、内存使用量和交互延迟。

高价值的 Konva 更改

  • 将静态内容和变化内容放在不同的图层上。
  • 对不接收事件的节点或图层设置 listening(false)
  • 当场景非常大时,隐藏位于可见区域之外的节点。
  • 测量确认能够提升渲染效果后,再缓存复杂且稳定的节点。
  • 当阴影、滤镜和大面积透明区域占据主要帧时间时,减少它们的使用。
  • 仅在数据发生变化后绘制。Konva 会自动批处理图层绘制。

不要缓存每个节点。每个缓存都会占用内存,并且其内容发生变化时会产生额外工作。

分离交互图层

此示例将 2,000 个非交互圆形放在一个图层上。由于 listening 为 false,该图层会跳过命中画布。第二个图层包含一个可拖动图形。

import Konva from 'konva';

const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: 420,
});

const backgroundLayer = new Konva.Layer({ listening: false });
const interactionLayer = new Konva.Layer();
stage.add(backgroundLayer, interactionLayer);

for (let index = 0; index < 2000; index += 1) {
backgroundLayer.add(
new Konva.Circle({
x: Math.random() * stage.width(),
y: Math.random() * stage.height(),
radius: 2 + Math.random() * 4,
fill: Konva.Util.getRandomColor(),
opacity: 0.55,
perfectDrawEnabled: false,
})
);
}

const handle = new Konva.Circle({
x: stage.width() / 2,
y: stage.height() / 2,
radius: 36,
fill: '#ff922b',
stroke: '#7c2d12',
strokeWidth: 3,
draggable: true,
});

const label = new Konva.Text({
x: 16,
y: 16,
text: 'The orange circle stays interactive',
fontSize: 18,
fill: '#111827',
});

interactionLayer.add(handle, label);

图层分离会产生开销,因为每个图层都会创建场景画布和命中画布。使用数量较少且更新模式明确的图层。

阅读所有 Konva 性能提示,了解动画、缓存、像素比和特定图形的指导。