# AntV
X6
是图编辑引擎 提供了开箱即用的交互组件和简单易用的节点定制能力 方便我们快速搭建流程图、DAG
图、ER
图等图应用 功能类似于 ProcessOn
G6
是图可视化引擎 它在高定制能力的基础上 提供了一系列设计优雅、便于使用的图可视化解决方案 能帮助开发者搭建属于自己的图可视化、图分析、或图编辑器应用
G2
是图可视化语法 一套面向常规统计图表 以数据驱动的高交互可视化图形语法 具有高度的易用性和扩展性 功能类似于 ECharts
# 安装 X6
(opens new window)
X6
支持 HTML、React、Vue、Angular
的使用 这次我们基于 Vue3
的环境来使用 X6
通过
npm install @antv/x6-vue-shape
安装X6
在
/src/views/antvDemo.vue
中引入X6
<script lang="ts" setup> // 引入 X6 依赖包 import '@antv/x6-vue-shape'; // 使用 Graph 进行图表的载体 import { Graph } from '@antv/x6'; </script>
1
2
3
4
5
6
# 初尝 X6
通过 X6
提供 graph.addNode()
能在页面中生成节点 并且通过 graph.addEdge()
使得节点关联起来
# 初始化画布
在
/src/App.Vue
中初始化页面样式<template> <div id="App"> <router-view></router-view> </div> </template> <script lang="ts" setup></script> <style lang="scss"> html, body, #App { height: 100%; } * { margin: 0; padding: 0; } </style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20在
/src/view/antvDemo.vue
中初始化画布<template> <div id="pageIndex"></div> </template> <script lang="ts" setup> import '@antv/x6-vue-shape'; import { Graph } from '@antv/x6'; import { onMounted } from '@vue/runtime-core'; let graph = null; onMounted(() => { // 初始化画布 graph = new Graph({ container: document.getElementById('pageIndex'), width: document.body.clientWidth, height: document.body.clientHeight, background: { color: '#fffbe6', }, snapline: true, // 对齐参考线 }); }); </script> <style lang="scss" scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25此时页面中就可以看到 浅黄色的画布
# 生成画布节点
X6
是通过JSON
数据 (opens new window)来快速定义 画布节点和连接线const nodeOne = { id: 'nodeOne', shape: 'rect', x: 40, y: 40, width: 80, height: 40, label: 'hello', }
1
2
3
4
5
6
7
8
9通过
graph.addNode(nodeOne)
添加节点到画布中通过
graph.addEdge()
将多个节点用线连接起来onMounted(() => { const nodeOne = graph.addNode({ id: 'nodeOne', x: 40, y: 40, width: 80, height: 40, label: 'hello', }); const nodeTwo = graph.addNode({ id: 'nodeTwo', x: 160, y: 180, width: 80, height: 40, label: 'x6', }); graph.addEdge({ source: nodeOne, target: nodeTwo, }); });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24此时 在页面就能看到两个节点被一条线给连接 并且 不管节点如何拖动 始终都是连接状态
# 深入 X6
跟着文档进一步了解 X6
的魅力吧
# 画布 Graph
Graph
是图的载体 它包含了图上的所有元素 (节点、边) 同时挂载了图的相关操作 (交互监听、元素操作、渲染)
通过 拖拽 (opens new window) 或者 滚动条 (opens new window) 来实现画布平移
const graph = new Graph({ panning: { enabled: true, // 是否允许拖拽画布 modifiers: 'shift', // 拖拽动作的修饰符 }, }) graph.isPannable() // 画布是否可以平移 graph.enablePanning() // 启用画布平移 graph.disablePanning() // 禁止画布平移 graph.togglePanning() // 切换画布平移状态
1
2
3
4
5
6
7
8
9
10
11
# 网格 Grid
网格是渲染、移动节点的最小单位 网格默认大小为 10px
渲染节点时表示以 10
为最小单位对齐到网格 如位置为 { x: 24, y: 38 }
的节点渲染到画布后的实际位置为 { x: 20, y: 40 }
移动节点时表示每次移动最小距离为 10px
网格类型
grid: Boolean|Object
const graph = new Graph({ grid:true grid: { size: 10, // 网格大小 10px visible: true, // 绘制网格,默认绘制 dot 类型网格 type: ['dot' | 'mesh'], // 网格样式 [ 小圆点 | 直线 ] }, })
1
2
3
4
5
6
7
8
# 节点 Node
通过 JSON
数据来快速添加两个矩形节点和一条边到画布中 并简单介绍了如何定制节点样式
基本属性
属性名 类型 默认值 描述 id
String
undefined
唯一标识符 markup
Markup
undefined
定义节点内部构成结构 attrs
Object
{}
节点属性样式 shape
String
Rect
渲染图形 可自定义 view
String
undefined
渲染的视图 zIndex
Number
0
画布层级 默认自动生成 visible
Boolean
true
是否可见 parent
String
undefined
父节点 children
String
[]
子节点 data
any
undefined
节点绑定的业务数据 x
Number
0 节点横轴坐标 y
Number
0 节点纵轴坐标 width
Number
1 节点宽度 height
Number
1 节点高度 angle
Number
0 节点旋转角度 内置节点
const nodeCylinder = graph.addNode({ id: 'nodeCylinder', x: 460, y: 480, width: 100, height: 200, label: '圆柱', shape: 'cylinder', // [Rect矩形、Circle圆形、Ellipse椭圆形、Cylinder圆柱形] angle: -30, attrs: { body: { fill: 'blue', }, label: { fill: 'white', }, }, });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 边 Edge
多个节点依赖着 Edge
来连接着 我们也可以自定义连接线的样式
基本属性
属性名 类型 默认值 描述 source
TerminalData
undefined
起始点 target
TerminalData
undefined
目标点 vertices
Point.PointLike[]
undefined
必经的路径点 router
RouterData
normal
路线的计算方式 label
Label
undefined
单个标签 基本案例
const edge = graph.addEdge({ source: { cell: nodeOne, port: 'out-port-1' }, target: nodeCircle, label: 'hasMany', vertices: [ { x: 100, y: 200 }, { x: 300, y: 120 }, ], }); // 后期添加标签 edge.setLabels(['edge']); edge.appendLabel('edge');
1
2
3
4
5
6
7
8
9
10
11
12
13-
edge.attr({ line: { // 起始点样式 sourceMarker: 'block', // 终点样式 targetMarker: { // SVG元素渲染箭头 tagName: 'path', // 填充颜色 fill: 'yellow', // 描边颜色 stroke: 'green', // 描边宽度 strokeWidth: 2, // 自定义箭头路径 需要定义一个向左指向坐标原点的箭头 d: 'M 20 -10 0 0 20 10 Z', }, }, });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 群组 Group
通过父子嵌套来实现群组,并提供了一系列获取和设置嵌套关系的方法 (opens new window)
基本用法
graph = new Graph({ container: document.getElementById('pageIndex'), width: document.body.clientWidth, height: document.body.clientHeight, panning: { enabled: true, modifiers: 'shift', }, grid: true, background: { color: '#fffbe6', }, // 限制子节点的移动范围 translating: { restrict(view) { const cell = view.cell; if (cell.isNode()) { const parent = cell.getParent(); if (parent) { return parent.getBBox(); // 只限制子节点不移动 // return { // x: cell.getBBox().x, // y: cell.getBBox().y, // width: 0, // height: 0, // }; } } return null; }, }, // 禁止所有节点移动 interacting: { nodeMovable: false, }, }); const child = graph.addNode({ x: 120, y: 80, width: 120, height: 60, zIndex: 10, label: 'Child', attrs: { body: { fill: 'green', }, label: { fill: '#fff', }, }, }); const parent = graph.addNode({ x: 80, y: 40, width: 320, height: 240, zIndex: 1, label: 'Parent\n(try to move me)', }); // 两个节点产生关系 parent.addChild(child);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 连接桩 Port
链接桩是节点上的固定连接点 并且分为 输入链接桩 和 输出连接桩 。
基本使用
Shape.Rect.define({ shape: 'my-rect', width: 160, height: 80, ports: { groups: { left: { position: 'left', attrs: { circle: { r: 6, magnet: true, // 定义连接桩功能是否启用 stroke: '#31d0c6', strokeWidth: 2, fill: '#fff', }, }, }, right: { position: 'right', attrs: { circle: { r: 6, magnet: true, stroke: '#31d0c6', strokeWidth: 2, fill: '#fff', }, }, }, }, }, }); graph.addNode({ x: 600, y: 600, shape: 'my-rect', label: 'Melon Port', ports: [ { id: 'port1', group: 'left', }, { id: 'port2', group: 'left', }, { id: 'port3', group: 'right', }, { id: 'port4', group: 'right', }, ], });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 节点和边的交互 - 连线规则 Connecting
定义连接关系
基本使用
graph = new Graph({ connecting: { // 连线时进入连接桩范围后自动吸附 snap: true, // 禁止背景吸附连接点 allowBlank: false, // 不允许节点之间重复连接 allowMulti: false, // 不允许连接节点 只能连接到连接桩 allowNode: false, }, });
1
2
3
4
5
6
7
8
9
10
11
12连线的回调函数
// 连接时回调 graph.on('edge:connected', args => { console.log(args); }); // 鼠标移入时 graph.on('edge:mouseenter', ({ edge, cell }) => { // 展示删除按钮 edge.addTools([ { name: 'button-remove', args: { distance: -40, // 删除时回调 onClick({ cell }) { graph.getCellById(cell.target.cell).removePort(cell.target.port); }, }, }, ]); // 展示移动连接桩 // 回调代码写在上面的 edge:connected 事件 cell.addTools([ 'source-arrowhead', { name: 'target-arrowhead', args: { attrs: { fill: 'red', }, }, }, ]); }); // 鼠标移出时移除删除小工具 graph.on('edge:mouseleave', ({ edge }) => { edge.removeTools(''); // if (edge.hasTool('button-remove')) { // edge.removeTool('button-remove'); // } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43