先放官网和图片,最好的学习地方仍然是官网。
官网:https://x6.antv.antgroup.com/
介绍:X6 是基于 HTML 和 SVG 的图编辑引擎,提供低成本的定制能力和开箱即用的内置扩展,方便我们快速搭建 DAG 图、ER 图、流程图、血缘图等应用。
这个流程图其实是Echarts没有的,相信很多和我一样的人。做项目要用到Echarts没有,然后就搜索到了这个。你如果会用Echarts,其实你已经会了一半,虽然Echarts是基于Canvas画图的,但是两者的用法和API调用基本相同,实际用起来去官网看API即可。

一、了解antv/x6
刚才上面提到了它是基于 HTML 和 SVG 的图编辑引擎,我们可以简单的理解成,我创建了一个SVG标签,给这的SVG标签设置各种的规则,然后特定的API/标签在里面画图,最后用事件触发把他们联系在一起。
步骤:
创建一个标签,成为容器container
声明一些需要的节点/边的数据
new一个实例对象,使用antv/x6的API在里面设置画布的规则
把数据放入这个实例中,在画布中渲染出来
这里示范的是vue2+antv/x6
<template> <div id="home"> <div> <button class="btn" @click="this.toSVG">导出</button> </div> <div id="container"></div> </div> </template> <script> // 引入antv/x6 import { Graph, DataUri } from "@antv/x6"; export default { name: "APP", data() { return { graph: null, // 画布实例对象 data: { nodes: [ { id: "node1", shape: "rect", x: 100, y: 100, width: 80, height: 40, label: "hello", }, { id: "node2", shape: "ellipse", x: 240, y: 300, width: 80, height: 40, label: "world", }, ], edges: [ { source: "node1", target: "node2", shape: "double-edge", }, ], }, }; }, created() {}, mounted() { this.initGraph(); }, methods: { /** 初始化流程图画布 */ initGraph() { /** 使用Graph API创造出实例对象,开始在SVG上画图/事件处理 */ this.graph = new Graph({ container: document.getElementById("container"), // 画布容器 width: 800, // 画布宽 height: 600, // 画布高 background: { color: "#ffffff", }, // 背景颜色设置 snapline: true, // 对齐线 // 配置连线规则 connecting: { snap: true, // 自动吸附 allowBlank: true, //是否允许连接到画布空白位置的点 allowMulti: false, //是否允许在相同的起始节点和终止之间创建多条边 allowLoop: false, //是否允许创建循环连线,即边的起始节点和终止节点为同一节点 highlight: true, //拖动边时,是否高亮显示所有可用的节点 validateEdge({ edge, type, previous }) { // 连线时设置折线 edge.setRouter({ name: "er", }); // 设置连线样式 edge.setAttrs({ line: { stroke: "#275da3", strokeWidth: 4, }, }); return true; }, }, panning: { enabled: false, // 支持画布拖拽平移 }, mousewheel: { enabled: true, // 支持滚动放大缩小 }, // 网格设置 grid: { type: "mesh", size: 20, // 网格大小 10px visible: true, // 渲染网格背景 args: { color: "#000000", // 网格线/点颜色 thickness: 2, // 网格线宽度/网格点大小 }, }, translating: { restrict: true, }, }); this.graph.fromJSON(this.data); }, /** 点击导出SVG */ toSVG() { this.graph.toSVG((dataUri) => { // 下载 DataUri.downloadDataUri(DataUri.svgToDataUrl(dataUri), "chart.svg"); }); }, }, }; </script> <style lang="scss" scoped> .btn { width: 10vw; height: 5vh; background: #bbffff; margin: 10px; border: 1px solid #000000; } </style>
复制

这样一个最简单的数据指向图就做好了,但是我们做的肯定没有那么简单,一般情况下需要可以进行链接,拖拽进入可以生成新的模块,连接的点那些可以连接/不可以连接等。这里就需要设置连接桩/交互/事件等,接着往下看,切记一定要沉下心来,这里出错了有的是不会显示的,需要配合Console和console.log一起来找。
二、Graph的配置
官网上是以画布/节点/边/连接桩/交互/事件/数据的顺序介绍的,我也以此开始讲解,官网更加清晰,可以直接移步官网查看。
画布
这个画布在上面的代码中已经写过了,就是设置画布的背景颜色/大小/缩放/网格等,这个比较简单,需要什么直接放进去就可以实现了。
节点
上面的代码我是把数据放在data里面(官网是放在initGraph()里面),最后通过数据的导入,实现画布的渲染。如果是十个以内的数据还好,一旦多起来,可以发现里面有很多的相同的属性/数据,这里的节点相当于是毛胚房,你想要什么样的房子自己装修就好。
官方解释:节点和边都有共同的基类 Cell,除了从 Cell 继承属性外,其他的可以在graph.addNode( )设置,可以实现定制节点/修改节点。
这里有一个坑一定要注意: graph.fromJSON()和graph.addNode()的顺序,graph.fromJSON()在前,不然会看不见添加的节点。
明白了这一个,那么我们就知道了,添加所有的这种相似的都可以使用此方法。如果我们要拖拽一个模板进来,就相当于在其中添加了一个定制的节点,其位置就是鼠标放开的位置。
步骤:
注册节点 Graph.registerNode()
使用注册的节点
添加这两个节点边(箭头)
//和官网一样直接添加在initGraph()里面就可以了 //这里有一个坑一定要注意: graph.fromJSON()和graph.addNode()的顺序,graph.fromJSON()在前,不然会看不见添加的节点 Graph.registerNode( "custom-node", { inherit: "rect", // 继承于 rect 节点 width: 100, height: 40, markup: [ { tagName: "rect", // 标签名称 selector: "body", // 选择器 }, { tagName: "image", selector: "img", }, { tagName: "text", selector: "label", }, ], attrs: { body: { stroke: "#8f8f8f", strokeWidth: 1, fill: "#fff", rx: 6, ry: 6, }, img: { "xlink:href": "https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png", width: 16, height: 16, x: 12, y: 12, }, }, }, true ); const source = graph.addNode({ shape: 'custom-node', // 可以直接使用上面注册过的 shape x: 40, y: 40, label: 'hello', }) const target = graph.addNode({ shape: 'custom-node', x: 160, y: 180, label: 'world', }) //修改节点的数据 source.prop("size", { width: 120, height: 50 }); // 修改 x 坐标 source.attr("rect/fill", "#ccc"); // 修改填充色,等价于 source.prop('attrs/rect/fill', '#ccc') graph.addEdge({ source, target, attrs: { line: { stroke: '#8f8f8f', strokeWidth: 1, }, }, })
复制
边(箭头)
这里官网上的意思是Edge边,但是我自己更习惯称为箭头,感觉更贴切吧。
edge里面的配置:
source: rect1, target: rect2, 源 ---> 节点
vertices: [ { x: 100, y: 200 }, { x: 300, y: 120 }, ], 顶点(边经过的顶点)
router: "orth", 路径:默认是直线;
connector: { name: "rounded", args: {}, },简写写 connector: 'rounded'连接器:圆形的
labels: [ { attrs: { label: { text: "edge", }, }, position: 0.4,}, ],设置标签文本、位置、样式等。简化写法:labels: ["edge"],
设置边上的箭头(这里可以直接设用已经预设好的)
attrs: { line: { sourceMarker: "block", // 实心箭头 targetMarker: { name: "ellipse", // 椭圆 rx: 10, // 椭圆箭头的 x 半径 ry: 6, // 椭圆箭头的 y 半径 }, }, },
复制
7.修改边与修改节点的方式有所不同,节点是不统一的,哪一个修改就是哪一个。边是统一的的,直接使用edge.prop("target", { x: 300, y: 300 }); // 修改终点e
dge.attr("line/stroke", "#ccc"); // 修改边颜色,等价于 edge.prop('attrs/line/stroke', '#ccc')
连接桩
就是每个节点连接的位置,有几个/在那个位置/应该怎么连接等。
步骤:
在 Graph.registerNode()注册的节点中配置ports,并通过 groups 选项来设置分组
groups内分上下左右,再对上下的port设置即可
在添加节点的时候graph.addNode因为加入了ports,也需要在其中配置ports的属性

交互(连接的配置)
主要记住这个连接的配置是在画布上的,new Graph({})
这个记不住的,直接翻过去照着一个个找,用就对了。
事件
看代码很容易理解,监听画布的 cell节点/单击、节点/单击、边/单击、空白区域/单击
这里数据太多,演示也多,直接去官网
graph.on("cell:click", ({ e, x, y, cell, view }) => {}); graph.on("node:click", ({ e, x, y, node, view }) => {}); graph.on("edge:click", ({ e, x, y, edge, view }) => {}); graph.on("blank:click", ({ e, x, y }) => {}); graph.on("cell:mouseenter", ({ e, cell, view }) => {}); graph.on("node:mouseenter", ({ e, node, view }) => {}); graph.on("edge:mouseenter", ({ e, edge, view }) => {}); graph.on("graph:mouseenter", ({ e }) => {});
复制
数据
导出数据
graph.toJSON()导出的是json数据
导出SVG或者png这里需要引入DataUri,这里导出的大小有问题,需要自己设置
// 引入antv/x6 import { Graph, DataUri } from "@antv/x6"; /** 点击导出SVG */ toSVG() { graph.toSVG((dataUri) => { // 下载 DataUri.downloadDataUri(DataUri.svgToDataUrl(dataUri), "chart.svg"); }); },
复制
导入数据
导入就只能是json数据了
graph.fromJSON({ nodes: [], edges: [],});
小结:其实看完这些,做起一些简单的还是ctrl+C / V就行了,但是涉及到逻辑的连接以及对数据的有一些要求时,其中的判断就会很多,慢慢写就好。
接下来,我会自己做一个逻辑的部署图,仅供参考/持续更新