Mxgraph学习(二)

814 阅读2分钟

前言

上一篇文章简单的使用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)

如果只是这样简单的导入那么会导致样式丢失,所以还有在导入前面加入样式的代码,如图

image.png

这样就会给每个图形添加上样式。但是我这里比较特殊,因为还有一个背景图片,且每个背景图片不一样,所以我还需要遍历每个mxCell,然后再添加图片。图片的位置信息,是保存在自定义xml的,如图:

image.png

所以整体的代码如下:

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会丢失一部分连线,如下图, 这个还需要再研究研究。

image.png

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第2天,点击查看活动详情