跳到主要内容

简单导出

Konva.Node.create() 从 JSON 还原节点树。还原舞台时必须指定容器。

用法​

要使用Konva反序列化一个JSON字符串,我们可以使用Konva.Node.create()方法,它可以解析JSON字符串并创建节点。 如果我们想反序列化一个舞台节点,我们还可以传入一个可选的container参数。

<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@10/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Simple Load Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var json = '{"attrs":{"width":578,"height":200},"className":"Stage","children":[{"attrs":{},"className":"Layer","children":[{"attrs":{"x":100,"y":100,"sides":6,"radius":70,"fill":"red","stroke":"black","strokeWidth":4},"className":"RegularPolygon"}]}]}';

// create node using json string
var stage = Konva.Node.create(json, 'container');
</script>

</body>
</html>

常见问题​

为什么还原舞台要传 container?​

因为舞台需要一个真实的 DOM 元素来挂载 canvas,而这个元素的 id 不可能在 JSON 里可靠地保存——同一份数据可能被还原到不同页面的不同容器里。

const stage = Konva.Node.create(json, 'container');

还原分组或图形则不需要这个参数,它们不直接持有 DOM。

还原之后为什么点不动、也没有反应?​

事件监听器没有被序列化,还原出来的是「哑」节点。

要恢复交互,还原后重新绑定。用 name 属性做标记是个实用做法—— name 会被序列化,还原后可以 find('.draggable') 批量找出需要绑定的节点。

JSON 是从哪个版本导出的重要吗?​

重要。Konva 的序列化格式随版本演进,10.6.0 就改变了 width、height 等属性的输出行为。

用新版本还原旧数据通常没问题(缺失的属性会用默认值), 但反过来——用旧版本还原新版本导出的数据——可能遇到无法识别的字段。

如果数据要长期保存,建议在存储时记下 Konva 版本号,便于日后排查。

与其他方案的取舍​

整体还原(一次 create() 建出整棵树)最简单,适合「打开一个保存的文件」。 代价是大场景下这是一次同步操作,节点多时会阻塞主线程。

增量还原是自己遍历数据、分批创建节点,配合 requestAnimationFrame 把工作摊到多帧。用户能先看到部分内容,感知上快得多。 代价是要自己写遍历逻辑。

一个折中做法:先还原可视区域内的节点,其余的延迟创建。 这需要数据里带有位置信息以便判断,也就意味着要用自己设计的数据结构, 而不是 Konva 的 JSON。