前言
接本专栏的上一篇antv X6新手教程,补充一些新的需求实现,丰富巩固antv X6的使用。此篇是以上一篇为基础的,如有初学者可以看本专栏的上一篇。
需求1:将编辑好的拓扑图展示在其他页面
一般在编辑完拓扑图或者流程图之后,前端需要把antv X6编辑的数据传给后端,然后再在其他页面去展示。比如我之前做过的一个业务逻辑:用户在拓扑编辑页面编辑好拓扑图之后,首页需要展示用户编辑好的那个拓扑图。
实现步骤
1、因为这是个demo案例,我就在同一个页面再放一个框当做首页的一个div做展示哈,先写一个div在下面,上面那个蓝色的div就是我们编辑的,下面绿色的用来展示。
2、因为绿色框里面也是要渲染节点数据的,只是不用自己拖进来,所以也需要初始化成antv X6的画布,先给下面那个盒子先加个id
<div id="containerDraw"></div>
再在data(){}里面定义一个实例对象
graphDraw: null, // 展示的画布实例对象
3、给绿色框的初始化函数,代码如下:
initGraphDraw() {const containerDraw = document.getElementById("containerDraw");this.graphDraw = new Graph({container: containerDraw, // 画布容器width: containerDraw.offsetWidth, // 画布宽height: containerDraw.offsetHeight, // 画布高background: false, // 背景(透明)snapline: true, // 对齐线// 配置连线规则connecting: {snap: true, // 自动吸附allowBlank: false, // 是否允许连接到画布空白位置的点allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边allowLoop: true, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点highlight: true, // 拖动边时,是否高亮显示所有可用的节点highlighting: {magnetAdsorbed: {name: "stroke",args: {attrs: {fill: "#5F95FF",stroke: "#5F95FF",},},},},router: {// 对路径添加额外的点name: "orth",},connector: {// 边渲染到画布后的样式name: "rounded",args: {radius: 8,},},},panning: {enabled: false,},mousewheel: {enabled: true, // 支持滚动放大缩小zoomAtMousePosition: true,modifiers: "ctrl",minScale: 0.5,maxScale: 3,},grid: {type: "dot",size: 20, // 网格大小 10pxvisible: true, // 渲染网格背景args: {color: "#a0a0a0", // 网格线/点颜色thickness: 2, // 网格线宽度/网格点大小},},});},
最后别忘记了在mounted()里面调用初始化函数
做到这里页面就如下图所示:
可以看到绿色框里面也有了网格,证明画布已经初始化好了。
4、渲染节点和连线数据
该专栏上篇文章最后写了保存画布的save() 函数,可以输出画布内的节点和连线数据,现在只需要再加一句话,就可以将上面蓝色框内的图像复制到绿色框内,代码如下:
//保存画布,并提交save() {console.log(this.graph.toJSON(), "graph");console.log(this.graph.getNodes(), "node");this.graphDraw.fromJSON(this.graph.toJSON());},
this.graphDraw.fromJSON(this.graph.toJSON());就是将graph的数据导出,拿到graphDraw内渲染。
效果展示
bug1
这里有一个bug,因为上下两个div是不一样大的,如果节点的xy坐标严格按照当时编辑的那样渲染就会发生以下现象:
可见渲染节点时需要适应当前画布的大小,只需要再加一句:
this.graphDraw.zoomToFit({ maxScale: 1 });
zoomToFit方法可以缩放画布内容,使画布内容充满视口。
效果展示:
bug2
做到这里突然发现一个问题,节点移动时可以移出画布:
查官方文档后找到解决办法,在画布配置项里加入以下代码,节点就不能被移动到画布之外了
translating: {restrict: true,
},
需求2:根据节点数据来改变节点的图片和标签等
比如我之前做过的一个业务:拓扑图上的节点有些时候需要告警,告警时节点的图片需要更改,节点下的文字也要更改。
实现步骤
1、先写一个按钮,用来触发更改事件:
<el-button@click="changeNode"style="background-color: #00cbd8"class="btnNormal">改变节点1</el-button>
2、定义改变节点的函数:
changeNode() {let cellData = this.graph.toJSON().cells;cellData.forEach((item) => {if (item.shape === "image" &&item.attrs.label.textWrap.text == "节点1") {this.graphDraw.getCellById(item.id).setAttrs({image: {["xlink:href"]: require("@/assets/img/virus.png"),},label: {textWrap: {text: "改变了!!",},},});}});},
这里的逻辑是,先获取到画布内的所有数据,然后循环判断形状是image并且是节点2的时候就更改图片路径和label标签,这里使用了getCellById()和setAttrs()两个方法。
效果展示
这里改变节点1就是举个例子,实际开发中可能需要根据data里面的数据去判断,通常将某些业务数据要存在节点/边的 data 上。如不懂可以看官方文档,其实antv X6的操作就是学会如何使用文档上的配置和方法,熟悉了就可以灵活使用。