Antv/X6
这里的背景是以vue3.2+antv/x6 2.8 为背景的学习,官网的文档是使用react书写的案例,需要摸索的地方还是有很多,下面开始
前提
假设你已经创建了vue ,如果不清楚怎么创建vue项目,建议前往官网学习Vue。使用组合式API开发,为了简便,没有使用路由等东西,就是使用TS + Less,但是 TS 使用的很烂,有问题拜托指出,谢谢。
快速上手
接下来我们就开始使用
安装 X6
# npm
$ npm install @antv/x6 --save
# yarn
$ yarn add @antv/x6
初始化画布
创建容器
首先我们要创建我们的画布容器,我们使用了id为container的div来当我们的容器
<template>
<div class="graph">
<!-- 1.创建容器 -->
<div id="container" class="container"></div>
</div>
</template>
引入 antv/x6
<script setup lang="ts">
// 1.引入vue和antv/x6
import { ref, onMounted } from "vue";
import { Graph } from "@antv/x6";
// 2.定义一个变量来接受这个
const graph = ref();
// 3. 在 onMounted 生命周期中才能访问到DOM节点,需要注意一下。
onMounted(() => {
// 4.定义画布
graph.value = new Graph({
container: document.getElementById("container") as HTMLElement,
width: 800,
height: 600,
background: {
color: "#F2F7FA", // 设置画布的背景颜色。
},
});
});
</script>
在上面的代码块中,我们定义了一个画布,以下对一些参数做一些解释。
container,目标容器width,画布的宽度height,画布的高度background,画布的背景,比如这里我们设置了背景的颜色
到这里我们应该在浏览器中就有一个画布了。

渲染节点和边
X6 支持 JSON 格式数据,该对象中 nodes 代表节点数据,edges 代表边数据,可以使用 attrs 属性来定制节点和边的样式(可以类比 CSS)。
定义节点和边的信息
<script setup lang="ts">
// 定义节点和边的信息
const data = {
nodes: [
{
id: "node1",
shape: "rect",
x: 40,
y: 40,
width: 100,
height: 40,
label: "hello",
attrs: {
// body 是选择器名称,选中的是 rect 元素
body: {
stroke: "#8f8f8f",
strokeWidth: 1,
fill: "#fff",
rx: 6,
ry: 6,
},
},
},
{
id: "node2",
shape: "rect",
x: 160,
y: 180,
width: 100,
height: 40,
label: "world",
attrs: {
body: {
stroke: "#8f8f8f",
strokeWidth: 1,
fill: "#fff",
rx: 6,
ry: 6,
},
},
},
],
edges: [
{
shape: "edge",
source: "node1",
target: "node2",
label: "x6",
attrs: {
// line 是选择器名称,选中的边的 path 元素
line: {
stroke: "#8f8f8f",
strokeWidth: 1,
},
},
},
],
};
</script>
下面我们来解释一下上面一坨代码的含义,其实大部分内容是重复的。我们从节点(nodes)开始.
nodes 解释
id,节点的唯一标识,如果不指定节点,那么 x6 会自动给我们生成 ID。shape,指定节点的图形,x6 给我们提供了很多的内置节点,比如我们这里使用的就是矩形。x,x 轴,在画布中水平向右为 x 轴正方向,垂直 x 轴向下为 y 轴正方向。此处指的就是节点在画布中 x 轴的位置。y,在画布中 y 轴的位置。width,节点的宽度height,节点的高度label,节点中间的描述性文字attrs,可以理解为css,是一个对象。比如我们这里body是选择器的名称,选中的是rect元素stroke,节点的矩形框描边颜色strokeWidth,节点的矩形框描边宽度fill,节点的矩形框填充颜色rx,节点的矩形直角的边框圆角水平半径ry,节点的矩形直角的边框圆角垂直半径
edges 解释
shape,指定边的类型source,源节点或者起始节点target,目标节点label,标签,或者简单说就是边上的文字attrs,line是选择器名称,选中的边的path元素
渲染
当我们定义好节点之后,我们就要开始渲染了。因为在Vue3之中,在onMounted之中才能拿到 Dom 节点,所以我们也需要再onMounted之中,才能拿到 Dom 赋值。
<script setup lang="ts">
// 1.引入vue和antv/x6
import { ref, onMounted } from "vue";
import { Graph } from "@antv/x6";
// 2.定义一个变量来接受这个
const graph = ref();
// 3. 在 onMounted 生命周期中才能访问到DOM节点,需要注意一下。
onMounted(() => {
// 4.定义画布
graph.value = new Graph({
container: document.getElementById("container") as HTMLElement,
width: 800,
height: 600,
background: {
color: "#F2F7FA", // 设置画布的背景颜色。
},
});
// 5.加载数据
graph.value.fromJSON(data);
});
</script>
然后去看浏览器,应该会有如下的画面:

我们在上面使用的时候,看到graph.value.fromJSON(data);这种用法,总是先.value之后再使用对应的方法,其实这个是因为我们创建变量的时候,使用的是ref创建的变量,使用ref创建的变量,只要不是在模版中使用,都是需要.value的。
到这里,快速上手就完毕了,就是这么简单。
画布
画布布是在 X6 中用于展示和编辑图形的区域,类似于绘图板的概念。通过画布,可以创建、移动、编辑和删除图形,包括节点、连接线、文本等。
画布自适应
我们在实例化Graph对象的时候,可以通过设置 width 和 height 固定画布大小,如果不设置,就会以画布容器大小初始化画布。但是我们有可能会遇到页面的 resize 事件,导致画布容器大小改变,导致画布元素显示异常。
resize 事件是 JavaScript 中一个针对浏览器窗口大小改变的事件。当用户调整浏览器窗口大小时,浏览器会触发 resize 事件,允许开发者在窗口大小改变时执行相关的代码。
window.addEventListener("resize", function () {
// 处理窗口大小改变事件
});
这时候,我们就需要设置autoResize来解决。
<script setup lang="ts">
// 1.引入vue和antv/x6
import { ref, onMounted } from "vue";
import { Graph } from "@antv/x6";
// 2.定义一个变量来接受这个
const graph = ref();
// 3. 在 onMounted 生命周期中才能访问到DOM节点,需要注意一下。
onMounted(() => {
// 4.定义画布
const graph = new Graph({
container: document.getElementById("container"),
autoResize: true,
});
// 5.加载数据
graph.value.fromJSON(data);
});
</script>
设置好之后,查看效果

当我们拉动浏览器的宽度的时候,我们发现,画布左右侧始终有一定的空间,画布会自适应变化宽度。
设置背景和网格
在antv/x6之中,可以通过 background 和 grid 两个配置来设置画布的背景以及网格。
背景
首先我们来看背景,他有多种情况。
color
背景颜色,支持所有 CSS background-color 属性的取值,如:
'red',颜色关键字'#f5f5f5',十六进制符号'rgba(255, 255, 128, 0.5)'函数符,红绿蓝透明度'hsla(50, 33%, 25%, 0.75)'
HSL圆柱坐标系统是指一种颜色空间表示方式,其中 HSL 代表色相、饱和度和亮度,圆柱坐标则表示这些参数的变化。
在HSL圆柱坐标系统中,色相是指颜色的种类或类别,如红色、黄色等,它沿着一个 360 度的色轮上变化。饱和度表示颜色的强度或纯度,取值范围为 0 到 1,0 表示灰度,1 表示完全饱和。亮度则表示颜色的亮暗程度,取值范围同样为 0 到 1,0 表示黑色,1 表示白色。最后一个值也是透明度,取值范围 0 到 1。
'radial-gradient(shape size at position, red, green)'
radial-gradient是CSS3中用来创建径向渐变效果的函数,使用 radial-gradient 函数可以创建从一个中心点向周围扩散的渐变效果。
shape可以是circle(圆形)或ellipse(椭圆形),size可以是closest-side(最近的边)、closest-corner(最近的角)、farthest-side(最远的边)或farthest-corner(最远的角),position表示渐变的中心点位置(可以是一个像素值或一个百分比),start-color表示起始颜色,last-color表示终止颜色。
比如:
background: radial-gradient(circle, #ff9d9d, #fe2d2d);
这将创建一个从中心向外扩散的圆形渐变效果,起始颜色为#ff9d9d,终止颜色为#fe2d2d。
image
背景图片的 URL 地址,这里需要值得注意的我们需要先导入,然后再使用
<script setup lang="ts">
import bgcImage from "@/antv-x6/bg2.b4f49dec.png";
onMounted(() => {
graph.value = new Graph({
container: document.getElementById("container") as HTMLElement,
width: 800,
height: 600,
background: {
image: bgcImage,
},
autoResize: true,
});
graph.value.fromJSON(data);
});
</script>
position
背景图片位置,支持所有 CSS background-position 属性的取值,默认为 'center'。
size
背景图片大小,支持所有 CSS background-size 属性的取值,默认为 'auto auto'。
repeat
背景图片重复方式,支持所有 CSS background-repeat 属性的取值,默认为 'no-repeat' 不平铺。
另外,还支持以下几个预定义值:
'watermark'水印效果。'flip-x'水平翻转背景图片。'flip-y'垂直翻转背景图片。'flip-xy'水平和垂直翻转背景图片。
画布拖拽(平移)和缩放
画布的拖拽和缩放通过 panning 和 mousewheel 配置来实现这两个功能
const graph = new Graph({
...,
panning: true,
mousewheel: true
})
节点
X6 是基于 SVG 的渲染引擎,可以使用不同的 SVG 元素渲染节点和边,非常适合节点内容比较简单的场景。如果我们需要复杂的场景,那么我们可以通过vue节点来实现。
添加节点
我们在最初的时候在setup中定义了一个graph属性,这个graph我们通过new创建了画布的对象。新增节点可以通过addNode方法,传入一个对象。
graph.value.addNode({
shape: "rect",
label: "矩形",
x: 100,
y: 40,
width: 100,
height: 40,
});
shape,节点的图形x,在画布中 x 轴的的位置y,在画布中的 y 轴的位置width,元素的宽度height,元素的高度label,矩形中间的文字
内置节点
在Antv/X6之中,也内置了很多节点,比如圆形,椭圆,矩形等等。
| shape 名称 | 描述 |
|---|---|
| rect | 矩形 |
| circle | 圆形 |
| ellipse | 椭圆 |
| polygon | 多边形 |
| polyline | 折线 |
| path | 路径 |
| image | 图片 |
| html | HTML 节点,使用 foreignObject 渲染 HTML 片段。 |
矩形
graph.value.addNode({
shape: "rect",
label: "矩形",
x: 100,
y: 40,
width: 100,
height: 40,
});

圆形
graph.value.addNode({
shape: "circle",
label: "矩形",
x: 100,
y: 40,
width: 100,
height: 40,
});

定制节点
可以通过 markup 和 attrs 来定制节点的形状和样式,markup 可以类比 HTML,attrs 类比 CSS。强烈建议仔细阅读 markup 和 attrs 文档。
但是个人认为这个适合做一些简单的节点,如果复杂的节点,推荐使用vue节点,后面会介绍到。
修改节点
在我们创建完成之后,还能够对节点进行一定的修改,我们还可以通过 API 修改节点的所有属性。我们会常用到下面两个方法:
const node = graph.addNode({
shape: "rect",
width: 100,
height: 40,
x: 100,
y: 100,
label: "edge",
});
console.log(node.prop());
比如:
source.prop("size", { width: 120, height: 50 }); // 修改元素的宽高
source.attr("rect/fill", "#ccc"); // 修改填充色,等价于 source.prop('attrs/rect/fill', '#ccc')
通常情况下,真实场景并不会像上面的示例,还给节点一个单独的名称,在实际过程中,我们一般是配合事件一起来进行使用,比如我们选中某个节点想要设置其边框颜色,他会自动监听画布中的点击事件,然后去进行对应的操作。
graph.value.on("cell:click", ({ e, x, y, cell, view }) => {
// cell 就是我们所需要的节点对象
cell.attr("body/stroke", "red");
});
或者说还有情况就是给画布中的所有对象都设置
const nodes = this.graph.getNodes(); // 获取画布中的所有节点
nodes.forEach((node) => {
const color = Color.random().toHex();
node.attr("body/fill", color);
});
边
如何添加边
graph.value.addEdge({
shape: "edge",
source: "node1",
target: "node2",
});
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| source | TerminalData | - | 源节点或起始点。其与节点的 ID 相同 |
| target | TerminalData | - | 目标节点或目标点。其与节点的 ID 相同 |
| vertices | Point.PointLike[] | - | 路径点。 |
| router | RouterData | - | 路由。 |
| connector | ConnectorData | - | 连接器。 |
| labels | Label[] | - | 标签。 |
| defaultLabel | Label | 默认标签 | 默认标签。 |
上面代码就是添加边的方法,source和target的值需要与节点的ID一致就可以将两个节点进行连接,如果你只是看看能不能创建边,其实还有种写法
graph.value.addEdge({
shape: "edge",
source: [100, 100],
target: [400, 100],
});
数组代表的是x轴和y轴。

vertices
路径点。边从起始点开始,按顺序经过路径点,最后到达终止点。
graph.value.addEdge({
source: "rect1",
target: "rect2",
vertices: [
{ x: 100, y: 200 },
{ x: 300, y: 120 },
],
});

router
路由 router 将对 vertices 进一步处理,并在必要时添加额外的点,然后返回处理后的点。
orth
正交路由,该路由在路径上添加额外的一些点,使边的每一条线段都水平或垂直正交。
graph.value.addEdge({
source,
target,
vertices: [
{ x: 100, y: 200 },
{ x: 300, y: 120 },
],
router: {
name: "orth",
args: {
padding: {
left: 50,
},
},
},
});

那两个圆圈的地方就是我们自己设置的vertices,其他的都是定义orth路由,自动生成的。
其他的版本可以看官网
manhattan
曼哈顿路由 'manhattan' 路由是正交路由 'orth' 的智能版本,该路由由水平或垂直的正交线段组成,并自动避开路径上的其他节点(障碍)。
同时需要注意的是,manhattan 路由的特性是自动避开路径中的障碍物,如果出现无法避开的情况,就会自动降级到 orth 路由,此时为了让开发者能够发现问题,在控制台增加了 warn:Unable to execute manhattan algorithm, use orth instead。
这个在最新的官网已经注明了。
如果你看着警告不爽,解决办法就是忽略参与计算的节点,但是这样就相当于没有manhattan就白用了一样。看自己选择吧。
labels 和 defaultLabel
graph.addEdge({
source,
target,
attrs: {
line: {
stroke: '#8f8f8f',
strokeWidth: 1,
},
},
labels: [
{
attrs: {
label: {
text: '40%', // 字体
stroke: '#aaa', // 颜色
},
},
position: 0.4, // 在线上的位置
},
{
attrs: {
label: {
text: '60%',
stroke: '#aaa',
},
},
position: 0.6,
},
],
})
}

定制边
基类派生
定制箭头有两种方式,一种是使用从基类派生出我们的边,并重写某些样式和方法。详细可以看antv/x6 1.0 版本,在 2.0 版本中没有明确说明这种方式。
import { Shape } from "@antv/x6";
//1. 派生出自己的边样式
const MyEdge = Shape.Edge({
markup: [
{
tagName: "path",
selector: "wrap",
attrs: {
fill: "none",
cursor: "pointer",
stroke: "transparent",
strokeLinecap: "round",
},
},
{
tagName: "path",
selector: "line",
attrs: {
fill: "none",
pointerEvents: "none",
},
},
],
attrs: {
wrap: {
connection: true,
strokeWidth: 10,
strokeLinejoin: "round",
},
line: {
connection: true,
stroke: "#333333",
strokeWidth: 2,
strokeLinejoin: "round",
targetMarker: {
tagName: "path",
d: "M 10 -5 0 0 10 5 z",
},
},
},
});
//2. 将边注册,这里用的就是Graph,不是实例后的画布对象 第一个参数是自定义的,只要在创建边的时候对应就行
Graph.registerEdge("edge1", MyEdge);
//3. 使用
graph.addEdge({
shape: "edge1",
source,
target,
});
箭头
对于边两端的箭头,antv/x6提供了内置箭头和自定义箭头两种方式
内置箭头
antv/x6提供了以下的几种箭头。
实心箭头(block)、经典箭头(classic)、菱形箭头(diamond)、交叉箭头(cross)、async、path、圆形箭头(circle)、圆形和加号箭头(circlePlus)、椭圆箭头(elipse)
定制箭头
工厂方法
在Graph原型上有个registerMarker方法,可以帮助我们自定义箭头
// 1.注册
Graph.registerMarker("image", (args: ImageMarkerArgs) => {
const { imageUrl, imageWidth, imageHeight, ...attrs } = args;
return {
...attrs, // 原样返回非特殊涵义的参数
tagName: "image", // 使用 <image> 标签渲染箭头,其余键值对都将作为该元素的属性。
width: imageWidth,
height: imageHeight,
"xlink:href": imageUrl,
};
});
//2. 使用
edge.attr({
line: {
sourceMarker: {
name: "image",
imageUrl:
"http://cdn3.iconfinder.com/data/icons/49handdrawing/24x24/left.png",
imageWidth: 24,
imageHeight: 24,
y: -12,
},
targetMarker: {
name: "image",
imageUrl:
"http://cdn3.iconfinder.com/data/icons/49handdrawing/24x24/left.png",
imageWidth: 24,
imageHeight: 24,
y: -12,
},
},
});
直接生成
我们可以通过实例对象上的暴露的方法直接生成边的同时,指定对应的样式,起始箭头和终止箭头使用了相同的 d 属性,这是因为x6会自动计算箭头方向,简单来说,在定义箭头时,只需要定义一个向左指向坐标原点的箭头即可。
graph.addEdge({
shape: "edge",
sourece: [100, 100],
target: [500, 500],
attrs: {
line: {
sourceMarker: {
tagName: "path",
d: "M 20 -10 0 0 20 10 Z",
},
targetMarker: {
tagName: "path",
fill: "yellow", // 使用自定义填充色
stroke: "green", // 使用自定义边框色
strokeWidth: 2,
d: "M 20 -10 0 0 20 10 Z",
},
},
},
});