前言
上一篇文章简单的使用mxgraph实现了一个图形化拖拽流程,考虑到要将图形化数据保存到数据库或者其他介质中,所以本篇内容将去探索如果将图像化数据导出为xml,并且实现回显。
导出xml
导出xml功能mxgraph已经有了完整的api,只需要调用即可。
var encoder = new mxCodec();
var node = encoder.encode(this.graph.getModel());
var xml = mxUtils.getPrettyXml(node);
导入xml
导入xml功能也是使用的mxgraph现有api去实现的,但是需要注意,如果xml中有除了mxCell定义的id之外,还有其他自定义的id,这时mxgraph会报错,会报一个id重复的异常(id:Duplicate ID)这个问题也是我试了好久才发现的。 例如我导出的xml如下:
<mxGraphModel>
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="2" value="开始" style="nodeStyle;image=/img/start.f26db4f5.png" parent="1" vertex="1">
<mxGeometry x="200" y="100" width="130" height="35" as="geometry" />
<Object name="开始" id="2" icon="/img/start.f26db4f5.png" nodeName="start" fullPath="" context="" operation="" as="data" />
</mxCell>
<mxCell id="3" value="按钮" style="nodeStyle;image=/img/button.144b855d.png" parent="1" vertex="1">
<mxGeometry x="200" y="210" width="130" height="35" as="geometry" />
<Object name="按钮" id="3" icon="/img/button.144b855d.png" nodeName="button" fullPath="" context="" operation="" as="data" />
</mxCell>
<mxCell id="4" value="断言" style="nodeStyle;image=/img/assert.2965bc33.png" parent="1" vertex="1">
<mxGeometry x="90" y="310" width="130" height="35" as="geometry" />
<Object name="断言" id="4" icon="/img/assert.2965bc33.png" nodeName="assert" fullPath="" context="" operation="" as="data" />
</mxCell>
<mxCell id="5" value="文本框" style="nodeStyle;image=/img/text.ab22920f.png" parent="1" vertex="1">
<mxGeometry x="410" y="380" width="130" height="35" as="geometry" />
<Object name="文本框" id="5" icon="/img/text.ab22920f.png" nodeName="text" fullPath="" context="" operation="" as="data" />
</mxCell>
<mxCell id="6" value="文本框" style="nodeStyle;image=/img/text.ab22920f.png" parent="1" vertex="1">
<mxGeometry x="140" y="450" width="130" height="35" as="geometry" />
<Object name="文本框" id="5" icon="/img/text.ab22920f.png" nodeName="text" fullPath="" context="" operation="" as="data" />
</mxCell>
<mxCell id="7" parent="1" source="2" target="3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8" parent="1" source="3" target="4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9" parent="1" source="3" target="5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="10" parent="1" source="4" target="6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="11" parent="1" source="5" target="6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
其中<Object name="文本框" id="5" icon="/img/text.ab22920f.png" nodeName="text" fullPath="" context="" operation="" as="data" />是我自定义的内容,但是这里也有个id,这样如果这个id和mxCell的id一样了就会导致导入失败。这个id是我后台判断节点类型用的,后来修改换了个名字就好了。
导入实现
// 导入
var doc = mxUtils.parseXml(xml)
var codec = new mxCodec(doc)
var model = this.graph.getModel()
codec.decode(doc.documentElement, model)
如果只是这样简单的导入那么会导致样式丢失,所以还有在导入前面加入样式的代码,如图
这样就会给每个图形添加上样式。但是我这里比较特殊,因为还有一个背景图片,且每个背景图片不一样,所以我还需要遍历每个mxCell,然后再添加图片。图片的位置信息,是保存在自定义xml的,如图:
所以整体的代码如下:
try {
// 设置全局样式
let nodeStyle = this.getNodePublicStyle(); // 这里获取全局样式。
this.graph.getStylesheet().putCellStyle("nodeStyle", nodeStyle);
// 导入xml到面板上。
var doc = mxUtils.parseXml(xml)
var codec = new mxCodec(doc)
var model = this.graph.getModel()
codec.decode(doc.documentElement, model)
// 然后再为各个mxCell添加背景样式
Object.values(this.graph.getModel().cells).forEach((cell,index) => {
if (cell.data != undefined) {
var icon = cell.data.icon; // 提取自定义xml节点中的图片位置信息。
self.graph.getModel().setStyle(cell, 'nodeStyle;image='+icon);
this.graph.refresh(cell) // 刷新图
}
})
} finally {
// Updates the display
this.graph.getModel().endUpdate()
}
结尾
这样一个简单的流程图的导入导出就算完成了,但是在实践的过程中发现导入xml会丢失一部分连线,如下图, 这个还需要再研究研究。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第2天,点击查看活动详情