AntV X6实战:实现节点四边自动连接与自定义箭头的完整配置
🔥 前言
你是否在用 AntV X6 开发流程图、拓扑图或低代码平台?
是不是经常遇到这些问题:
连线不能自动吸附到节点上下左右四条边?
箭头样式太丑,想自定义却不知道怎么写?
快捷键、撤销、导出图片功能不会配
✅ 每一行代码的中文注释
✅ 所有可选项一网打尽(不用查文档)
✅ 插件安装命令 + 使用说明
✅ 适合 Vue 项目,新手也能轻松上手
🎯 看完就能跑通,拿来即用!一键复制所有代码块即可使用
🧩 一、你需要安装的 NPM 包(复制粘贴即可)
核心库(必须)
npm install @antv/x6
如果你用 Vue 组件作为节点(比如带按钮/输入框的复杂节点)
npm install @antv/x6-vue-shape
官方推荐插件包(包含 History、Selection、Export)
npm install @antv/x6-plugin-export
可选:支持从侧边栏拖拽创建节点
npm install @antv/x6-plugin-dnd
可选:更强大的快捷键管理
npm install @antv/x6-plugin-keyboard
💡 提示:即使你暂时不用某些功能,也建议先装上 @antv/x6-plugin-export,它包含了最常用的三大插件
🧰 二、基础配置文件 baseConfig.js
// baseConfig.js
// 所有图形设置集中在这里,方便统一维护
import { Shape } from '@antv/x6';export const baseConfig = {// 节点移动限制:拖动时不能移出画布,防止节点"丢失"translating: {restrict: true},// 不显示网格背景grid: false,// 设置画布为白色背景background: {color: '#ffffff'},// 鼠标滚轮缩放配置mousewheel: {enabled: true, // 启用滚轮缩放zoomAtMousePosition: true, // 以鼠标位置为中心缩放modifiers: 'ctrl', // 需按住Ctrl键才能缩放minScale: 0.5, // 最小缩放比例50%maxScale: 3, // 最大缩放比例300%showNodeSelectionBox: true, // 缩放时显示选中框pointerEvents: 'auto' // 缩放期间仍可交互},// 画布平移配置:按住Alt键拖动画布panning: {enabled: true,modifiers: 'alt'},// 连线系统核心配置connecting: {// 路由器:控制连线路径('normal'表示直线)router: 'normal',// 连接器:控制连线形状('normal'表示直线)connector: { name: 'normal' },// 磁铁行为:整个节点都是磁铁magnet: 'body',// 锚点:从节点中心出发anchor: 'center',// ✅ 关键配置:实现四边自动连接的核心// 'boundary'表示连线会自动吸附到节点边缘connectionPoint: 'boundary',// 开启自动吸附snap: true,// 禁止连接空白区域allowBlank: false,// 禁止同两个节点间多条连线allowMulti: false,// 禁止自环(自己连自己)allowLoop: false,// 允许连接普通节点allowNode: true,// 禁止连接已有边allowEdge: false,// 禁止连接"连接桩"(当前仅用于视觉展示)allowPort: false,// 连接时高亮目标节点highlight: true,// 自定义验证逻辑:禁止自己连自己validateConnection({ sourceView, targetView }) {return sourceView !== targetView;},// 创建新连线时的样式createEdge() {return new Shape.Edge({// zIndex: -1 让连线在所有节点下面(不会遮挡)zIndex: -1,attrs: {line: {// 线条颜色(浅灰蓝)stroke: '#D3D8EA',// 线宽strokeWidth: 1,// 箭头样式(实心三角)targetMarker: {name: 'block', // 实心三角箭头width: 12, // 宽度height: 8, // 高度offset: -30 // 往回退一点,避免太贴边}}}});}},// 高亮反馈:当鼠标靠近可连接节点时显示描边highlighting: {magnetAdsorbed: {name: 'stroke',args: {attrs: {fill: '#fff',stroke: '#5F95FF',strokeWidth: 2}}}},// 连接过程中的提示(蓝色边框)edgeAvailable: {name: 'stroke',args: {padding: 4, // 边框距离节点有空隙color: '#5F95FF', // 主题蓝色(比红色更合理)width: 3 // 提示边框宽度}},// 所有元素都可交互interacting: () => true,// 快捷键绑定bindShortcuts(graph) {// 删除选中的节点或连线graph.bindKey(['delete', 'backspace'], () => {const cells = graph.getSelectedCells();if (cells.length > 0) {graph.removeCells(cells);}return false; // 阻止浏览器默认行为});// 撤销操作graph.bindKey('ctrl+z', () => graph.undo());graph.bindKey('cmd+z', () => graph.undo()); // Mac// 重做操作graph.bindKey('ctrl+y', () => graph.redo());graph.bindKey('cmd+shift+z', () => graph.redo()); // Mac// 全选graph.bindKey('ctrl+a', () => graph.selectAll());}
};
连接桩配置 cuPort.js(仅视觉展示)
// cuPort.js
// 定义一个"连接点"(小蓝点),默认隐藏
export const cuPort = {groups: {group1: {position: [20, 20] // 放在节点内部 x=20, y=20 的位置}},items: [{group: "group1",id: "port1",attrs: {circle: {r: 6, // 半径 6pxmagnet: true, // 可作为连接吸附点stroke: "#ffffff", // 白色边框strokeWidth: 2,fill: "#5F95FF", // 蓝色填充visibility: 'hidden' // 默认隐藏(hover 时可用 JS 显示)}}}]
};
插件统一管理 plugins.js
// plugins.js
// 统一注册常用插件,避免重复注册
import { History, Selection, Export } from '@antv/x6-plugin-export';export const usePlugins = (graph) => {graph// 撤销 / 重做功能.use(new History({ enabled: true }))// 多选 & 框选功能.use(new Selection({enabled: true,multiple: true,rubberband: true,movable: true,showNodeSelectionBox: true,pointerEvents: "none"}))// 导出功能.use(new Export());
};
🚀 初始化函数 initializeGraph.js
// initializeGraph.js
// DnD 插件用于从外部拖入节点
import { Dnd } from '@antv/x6-plugin-dnd';
import { baseConfig } from './baseConfig';
import { usePlugins } from './plugins';// 假设这是你的Vue组件中的方法
function initializeGraph(proxy) {// 创建图形实例const graph = new Graph({container: proxy.$refs.graphContainer, // 挂载到页面上的divwidth: '100%',height: '60%',interactive: true,...baseConfig, // 使用baseConfig的所有配置// 合并mousewheel配置,确保不丢失关键设置mousewheel: {...baseConfig.mousewheel},// 启用选择功能selecting: {enabled: true,multiple: true,className: 'my-selecting',movable: true}});// 创建拖拽插件(用于从侧边栏拖入节点)const dnd = new Dnd({target: graph,scaled: false // 拖入时不自动缩放位置});// 注册Vue节点(如果你用了Vue组件作为节点)// useVueNode(graph);// 使用插件(只调用一次)usePlugins(graph);// 绑定快捷键baseConfig.bindShortcuts(graph);// 初始化撤销按钮状态let undoDisabled = false;undoDisabled = graph.canUndo();// 监听历史变化,动态更新按钮状态graph.on('history:change', () => {undoDisabled = !graph.canUndo();});return { graph, dnd, undoDisabled };
}
📘常见需求快速参考表
// 直线
connector: { name: 'normal' }// 圆角折线
connector: { name: 'rounded' }// 曲线
connector: { name: 'smooth' }// 跳跃线(避让交叉)
connector: { name: 'jumpover', args: { size: 10 } }
✅ 箭头类型大全(替换 targetMarker.name)
// 实心三角(当前使用)
name: 'block'// 空心箭头
name: 'classic'// 菱形
name: 'diamond'// 圆圈
name: 'circle'// 异步箭头
name: 'async'// 自定义路径
name: 'path',
d: 'M 0 0 L 10 5 L 0 10 z'
✅ 锚点(anchor)可选值(替换 anchor 配置)
// 中心(当前使用)
anchor: 'center'// 上边中点
anchor: 'top'// 右边中点
anchor: 'right'// 下边中点
anchor: 'bottom'// 左边中点
anchor: 'left'// 自定义坐标(相对左上角)
anchor: [20, 30]// 底部偏移x方向20px
anchor: { name: 'bottom', args: { dx: 20 } }