antvis/chart-visualization-skills274 installs
antv-x6-editor
X6 图编辑引擎代码生成技能,支持流程图、DAG、ER图、血缘图等图编辑场景的节点/边/端口/交互/插件配置
How do I install this agent skill?
npx skills add https://github.com/antvis/chart-visualization-skills --skill antv-x6-editorIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides comprehensive instructions for generating code using the AntV X6 library. It utilizes strong instructional constraints to ensure API compatibility. A potential security surface is identified in the provided templates for custom HTML nodes, where data from the graph model is rendered using innerHTML without explicit sanitization, creating a surface for indirect prompt injection or XSS if graph data is sourced from untrusted users.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
X6 图编辑引擎代码生成技能
核心约束(必须遵守)
<!-- CONSTRAINTS:START -->X6 3.x 关键约束(强制)
graph.render()不存在:X6 3.x 中new Graph()/addNode/addEdge/fromJSON均自动渲染,代码中不得出现graph.render()。- 不得声明
container变量:运行环境会作为函数参数注入container。Graph 初始化只使用字符串字面量container: 'container',禁止const/let/var container = ...,也禁止document.getElementById('container')。 - 使用插件方法前必须先
graph.use(new Plugin(...))注册对应插件:graph.toPNG / toSVG / toJPEG依赖Export;graph.select / unselect依赖Selection;graph.undo / redo依赖History;graph.copy / paste / cut依赖Clipboard;graph.bindKey依赖Keyboard。未注册插件时对应方法不存在。 - 自定义 shape 必须先注册再使用:
Graph.registerNode(name, def)/Graph.registerEdge(name, def)/Shape.HTML.register({ shape, ... })必须在首次addNode / addEdge之前完成。 @antv/x6仅导出 11 个插件类:Clipboard、Dnd、Export、History、Keyboard、MiniMap、Scroller、Selection、Snapline、Stencil、Transform。mousewheel、embedding、panning、connecting、translating、interacting、background、grid是new Graph()的构造选项,不是插件,不得 import 同名类、不得graph.use(new XxxClass())。例:滚轮缩放写在 Graph 构造中mousewheel: { enabled: true, zoomAtMousePosition: true, modifiers: ['ctrl'] }。- 节点/边动画使用
cell.animate(keyframes, options)(Web Animations API 风格):X6 3.x 没有node.transition(path, target, options)方法。源码中transition仅作为node.translate(tx, ty, { transition })/node.rotate(deg, { transition })的 options 字段存在(boolean | KeyframeEffectOptions),并非独立方法。示例:
多步属性变更可用// 通用动画 node.animate( { fill: ['#fff', '#1890ff'], transform: ['scale(1)', 'scale(1.2)'] }, { duration: 500, iterations: 1, fill: 'forwards' }, ); // 仅平移过渡 node.translate(120, 0, { transition: { duration: 500, easing: 'ease-in-out' } });graph.startBatch('animate'); cell.attr(...); graph.stopBatch('animate');包装。
初始化规范
container参数必填,必须使用字符串形式container: 'container',运行时环境会自动解析为 DOM 元素- 必须设置背景色:
background: { color: '#F2F7FA' },所有画布都需要统一的浅蓝灰色背景 - 不要添加
grid配置,除非用户明确要求显示网格 - 不要设置
width/height,除非用户明确指定画布尺寸;画布默认自适应容器大小 - 导入方式:
import { Graph } from '@antv/x6',仅导入实际使用到的类 - 禁止无条件导入
Shape:仅在使用Shape.HTML.register()等 Shape 静态方法时才导入Shape - 插件从
'@antv/x6'直接导入,如import { Graph, Selection, History } from '@antv/x6' - 禁止使用
@antv/x6-plugin-xxx独立包导入(已废弃) - 标准初始化模板:
import { Graph } from '@antv/x6'; const graph = new Graph({ container: 'container', background: { color: '#F2F7FA' }, });
节点操作规范
- 优先使用
graph.addNode()逐个添加节点,而非graph.fromJSON()批量导入(除非用户明确要求批量加载数据) - 内置 shape:
'rect'、'circle'、'ellipse'、'polygon'、'polyline'、'path'、'text'、'text-block'、'image'、'html' - 节点样式通过
attrs配置,遵循 SVG 属性命名 - 节点位置通过
x、y设置(左上角坐标),尺寸通过width、height设置 - 默认节点样式(除非用户指定其他样式,所有节点统一使用此默认样式):
attrs: { body: { stroke: '#8f8f8f', strokeWidth: 1, fill: '#fff', rx: 6, ry: 6 }, } - 禁止在 attrs 中使用 CSS 属性名(如
background-color),必须用 SVG 属性(如fill)
边操作规范
- 使用
graph.addEdge({ source, target, ... })添加边 source/target可以是:节点实例、节点 ID 字符串、{ cell: node, port: 'portId' }对象、坐标{ x, y }- 边样式:
attrs: { line: { stroke, strokeWidth, strokeDasharray, targetMarker, sourceMarker } } - 默认边样式(除非用户指定其他样式):
attrs: { line: { stroke: '#8f8f8f', strokeWidth: 1 } } - 箭头:
targetMarker: 'classic'(经典箭头)、'block'、'circle'、'diamond' - 路由器:
router: 'orth'(正交)、'manhattan'、'metro'、'er' - 连接器:
connector: 'rounded'(圆角)、'smooth'(贝塞尔曲线)、'jumpover'
连接桩(Ports)规范
- 连接桩定义在节点配置的
ports字段中 - 端口组:
ports: { groups: { groupName: { position, attrs, ... } }, items: [{ id, group }] } - position 取值:
'top'、'bottom'、'left'、'right' - 端口是连线的锚点,设置
attrs: { circle: { magnet: true } }允许从端口拖出连线 - 必须设置
magnet: true才能从该端口发起或接收连线
交互配置规范
- 连线交互在 Graph 配置中通过
connecting字段设置 connecting: { allowBlank: false, router: 'orth', connector: 'rounded', createEdge() {...} }- 节点移动限制:
translating: { restrict: true }或传函数限制区域 - 嵌入:
embedding: { enabled: true }允许节点拖入分组
插件使用规范
- 插件从
@antv/x6导入,通过graph.use(new Plugin(options))注册 - 可用插件:
Selection、Snapline、History、Clipboard、Keyboard、Scroller、MiniMap、Transform、Export、Stencil、Dnd - Selection:
graph.use(new Selection({ enabled: true, rubberband: true })) - Snapline:
graph.use(new Snapline({ enabled: true })) - History:
graph.use(new History({ enabled: true })) - Clipboard:
graph.use(new Clipboard({ enabled: true })) - Keyboard:
graph.use(new Keyboard({ enabled: true })) - Scroller:
graph.use(new Scroller({ enabled: true })) - MiniMap:
graph.use(new MiniMap({ enabled: true, container: minimapContainer })) - Transform:
graph.use(new Transform({ resizing: { enabled: true }, rotating: { enabled: true } })) - Export:
graph.use(new Export())(注册后可调用graph.toPNG()/graph.toSVG()) - 动态控制:
graph.enablePlugins('selection')/graph.disablePlugins('selection') - 禁止在 Graph 构造函数中直接传入
selecting、snapline等选项(3.x 不支持)
序列化规范
- 导出:
const data = graph.toJSON()返回{ cells: [...] }对象 - 导入:
graph.fromJSON(data)加载整个图数据 - 清空:
graph.clearCells()清除所有元素 - 禁止手动构造 cells 数组中的内部字段(如
zIndex、parent),应通过 API 操作
事件规范
- 节点事件:
graph.on('node:click', ({ node, e }) => {...}) - 边事件:
graph.on('edge:click', ({ edge, e }) => {...}) - 画布事件:
graph.on('blank:click', ({ e }) => {...}) - 变更事件:
graph.on('node:moved', ({ node }) => {...}) - 事件回调参数是对象,不是位置参数:
({ node, e })而非(node, e)
导入规范
- 所有使用到的类都必须出现在 import 语句中:如使用
Selection,必须import { Graph, Selection } from '@antv/x6' - 禁止使用
Graph.Selection、Graph.Keyboard等命名空间写法(不存在) - 禁止使用未导入的类:
new Selection(...)必须对应import { Selection } from '@antv/x6' - import 自检清单(强制,输出代码前必须逐行核对):对代码中每一个
new XxxYyy(...)调用,XxxYyy必须字面出现在第一行import { ..., XxxYyy } from '@antv/x6'的花括号内。常见漏写:Selection、Keyboard、History、Clipboard、Snapline、MiniMap、Transform、Scroller、Export、Stencil、Dnd、Shape(用到Shape.HTML.register时)。 - import 漏写为何会变成
Illegal constructor等运行时错:评测/Playground 环境用 UMD 构建(window.X6)执行代码,而不是真正的 ES Module。Selection、Keyboard等会根据 import 列表从window.X6解构出来;如果 import 漏写,标识符Selection会回退到window.Selection(浏览器原生 Selection 接口),new Selection({...})会抛Failed to construct 'Selection': Illegal constructor。Keyboard/History等同理(会is not a constructor)。 - import 漏写的标准修法:把所有用到的插件类合并到同一行
import { Graph, Selection, Keyboard, History, ... } from '@antv/x6';,不要分多行 import,也不要遗漏。
节点工具(Tools)规范
- 添加工具:
node.addTools([{ name: 'button-remove', args: { x: 0, y: 0 } }])或graph.addTools(node, [...]) - 移除工具:
node.removeTools()或graph.removeTools(node) - 检查工具:
node.hasTools() - 禁止使用
node.hideTools()/node.showTools()(3.x 不存在此 API) - 悬停显示/隐藏工具的正确方式:
graph.on('node:mouseenter', ({ node }) => { node.addTools([{ name: 'button-remove', args: { x: 0, y: 0 } }]); }); graph.on('node:mouseleave', ({ node }) => { node.removeTools(); });
渐变色规范
- X6 attrs 中
fill支持渐变对象语法,禁止直接操作graph.defs或document.createElementNS创建 SVG 渐变 - 线性渐变正确写法:
attrs: { body: { fill: { type: 'linearGradient', stops: [ { offset: '0%', color: '#0000ff' }, { offset: '100%', color: '#00ff00' }, ], }, }, }
代码输出规范
- 必须输出纯 JavaScript,禁止使用 TypeScript 语法(如
private、类型注解: string、as类型断言) - HTML 自定义节点使用
Shape.HTML.register({ shape, html, effect })注册自定义 shape,禁止使用class extends Node方式 - 禁止
Graph.registerHTMLComponent(name, factory)—— 这是 X6 2.x 旧 API,3.x 源码已无此方法。所有 HTML 节点统一通过Shape.HTML.register注册(详见references/core/x6-core-html-shape.md) effect数组指定哪些属性变化时触发重新渲染(如['data']);纯静态展示节点不要加 effect- HTML 节点正确写法:
import { Graph, Shape } from '@antv/x6'; Shape.HTML.register({ shape: 'my-html', effect: ['data'], html(node) { const div = document.createElement('div'); div.style.width = '100%'; div.style.height = '100%'; div.innerHTML = node.getData().content || ''; return div; }, }); const graph = new Graph({ container: 'container' }); graph.addNode({ shape: 'my-html', x: 100, y: 100, width: 200, height: 80, data: { content: '<div>Hello</div>' } });
Stencil 插件规范
- Stencil 通过
graph.use(new Stencil({ target: graph, groups: [...] }))注册 - 注册后通过
graph.getPlugin('stencil')获取实例,将stencil.container挂载到 DOM - Stencil 内的节点模板使用
graph.createNode(...)创建(非graph.addNode),再通过stencil.load(nodes, groupName)加载
动态端口规范
- 使用
node.addPort()动态添加端口时,必须在节点初始化时预定义对应的 ports.groups - 如果没有预定义 group,端口无法正确定位,可能导致渲染异常
- 正确写法:
const node = graph.addNode({ ..., ports: { groups: { in: { position: 'left', attrs: { circle: { r: 4, magnet: true, stroke: '#8f8f8f', fill: '#fff' } } }, out: { position: 'right', attrs: { circle: { r: 4, magnet: true, stroke: '#8f8f8f', fill: '#fff' } } }, }, }, }); node.addPort({ id: 'port1', group: 'out' }); registerNode+addNode的 ports 合并陷阱(强约束):Graph.registerNode(name, { ports: { items: [{ id: 'in1', group: 'in' }] } })之后,如果再graph.addNode({ shape: name, ports: { items: [{ id: 'in1', group: 'in' }] } }),X6 内部Cell构造时ObjectExt.merge(defaults, metadata)会按数组下标合并、node.addPorts走的也是[...current, ...new]简单拼接,不会去重,运行时直接抛Error: Duplicitied port id.。正确做法二选一:- 在
registerNode里只声明ports.groups,把ports.items留给addNode/ 后续node.addPort提供; - 或在
registerNode里完整声明ports.items,addNode时不再传ports.items(如需追加端口,调用node.addPort({ id: '新id', group: 'xxx' }),且新 id 不能与 registry 里已声明的重名)。
- 在
DOM/CSS 操作规范(HTML 节点 / Stencil / 自定义工具)
- HTML 节点
html(node)回调里给 DOM 设样式时,禁止直接写连字符属性:el.style.box-sizing = '...'、el.style.font-size = '...'会被 JS 解析为el.style.box - sizing = ...,抛Invalid left-hand side in assignment。正确写法二选一:- 驼峰:
el.style.boxSizing = 'border-box'、el.style.fontSize = '14px'、el.style.backgroundColor = '#fff'; - 方括号:
el.style['box-sizing'] = 'border-box'、el.style['font-size'] = '14px'; - 多条样式优先用
el.style.cssText = 'box-sizing:border-box;font-size:14px;'或Object.assign(el.style, { boxSizing: 'border-box', fontSize: '14px' })。
- 驼峰:
- 同理,
el.classList.add('...')/el.setAttribute('data-x', '...')是合法 API;禁止el.class = '...'/el['class-name'] = ...。
不存在的 API(禁止使用)
- 禁止
graph.scrollToCell()→ 正确方式:graph.centerCell(cell)滚动并居中到指定 cell - 禁止
graph.highlightCell()/graph.highlightNode()→ 正确方式:通过node.attr('body/stroke', '#f00')或添加 CSS class 实现高亮 - 禁止
Shape.Cylinder/Shape.Diamond等不存在的内置 Shape → 用'rect'+rx/ry或'polygon'自定义 - 禁止
Shape.Edge.define()/Shape.Node.define()→ 正确方式:Graph.registerEdge()/Graph.registerNode() - 禁止
Shape.Group/Shape.Group.define()/new Shape.Group()→ X6 3.x 的Shape命名空间没有Group导出(实际只有Circle / Edge / Ellipse / HTML / Image / Path / Polygon / Polyline / Rect / TextBlock,运行时会报Cannot read properties of undefined (reading 'define'))。父子分组的正确方式:直接graph.addNode({ shape: 'rect', ... })创建一个普通节点作为父节点,再通过parent.addChild(child)/parent.embed(child)建立父子关系;或用Graph.registerNode('my-group', { inherit: 'rect', markup: [...], attrs: {...} })注册一个自定义分组形状再addNode({ shape: 'my-group' })。 - 禁止 把
Embedding当插件 import / new /graph.use(new Embedding(...))→ X6 3.x 没有Embedding插件类(运行时会报Embedding is not a constructor)。节点嵌入是 Graph 构造选项:new Graph({ container, embedding: { enabled: true, findParent: 'bbox', frontOnly: false, validate: ({ child, parent }) => true } })。Hover 高亮通过highlighting.embedding配置,嵌入/解除嵌入事件为node:embedding/node:embedded。 - 禁止
history.batch()→ 正确方式:graph.startBatch('custom'); ...; graph.stopBatch('custom');或graph.batchUpdate(() => { ... }) - 禁止
graph.defs/graph.svgDoc/document.createElementNS('...', 'linearGradient' | 'defs' | 'marker')→ X6 3.x 不暴露graph.defs/graph.svgDoc,运行时会报Cannot read properties of undefined。正确方式:- 节点/边普通
fill渐变:直接用 attrs 中的渐变对象语法(fill: { type: 'linearGradient', stops: [...] }) - 自定义 marker 需要渐变填充:先
const id = graph.defineGradient({ type: 'linearGradient', stops: [{ offset: 0, color: '#f00' }, { offset: 1, color: '#0f0' }] }),再在 marker 对象里写fill: \url(#${id})`` - 自定义 marker / filter 同理使用
graph.defineMarker(options)/graph.defineFilter(options)
- 节点/边普通
渲染输出规范(必须遵守)
- 画布初始化后必须存在至少一个
graph.addNode/graph.addEdge/graph.fromJSON调用,确保画布有可视内容。即使用户 query 只描述了交互(panning / mousewheel / 插件等)配置,也必须自行补 2~3 个示例节点 + 1 条边作为渲染载体,否则视觉验证会被判定为「白屏」。 - 所有节点/边添加完成后,必须在末尾调用
graph.centerContent()(或在画布需要随内容缩放时使用graph.zoomToFit({ padding: 20, maxScale: 1 }))。X6 默认不会自动居中,缺失该调用会导致内容偏向左上角、视觉评分不通过。两者二选一,不可同时调用。 - 多个交互(
panning+mousewheel+Selectionrubberband)同时启用时,必须用modifiers错开触发条件(例如:panning 用'shift',mousewheel 用'ctrl',rubberband 留空)。禁止把'mouseWheel'放进panning.eventTypes同时又启用mousewheel,两者会争抢滚轮事件。
禁止的错误模式
❌ 使用已废弃的独立插件包
// 错误:独立插件包已废弃
import { Selection } from '@antv/x6-plugin-selection';
import { History } from '@antv/x6-plugin-history';
// 正确:从 @antv/x6 直接导入
import { Graph, Selection, History } from '@antv/x6';
const graph = new Graph({ container: 'container' });
graph.use(new Selection({ enabled: true, rubberband: true }));
graph.use(new History({ enabled: true }));
❌ 在构造函数中传入插件选项
// 错误:3.x 不支持构造函数选项模式
const graph = new Graph({
container: 'container',
selecting: { enabled: true }, // ❌
snapline: { enabled: true }, // ❌
history: { enabled: true }, // ❌
});
// 正确:使用 graph.use() 注册插件
import { Graph, Selection, Snapline, History } from '@antv/x6';
const graph = new Graph({ container: 'container' });
graph.use(new Selection({ enabled: true }));
graph.use(new Snapline({ enabled: true }));
graph.use(new History({ enabled: true }));
❌ 混淆 CSS 属性和 SVG 属性
// 错误:使用 CSS 属性名
attrs: {
body: {
'background-color': '#fff', // ❌
'border-radius': '6px', // ❌
}
}
// 正确:使用 SVG 属性名
attrs: {
body: {
fill: '#fff', // ✅ 背景色
rx: 6, // ✅ 圆角
ry: 6,
stroke: '#8f8f8f', // ✅ 边框色
strokeWidth: 1, // ✅ 边框宽度
}
}
❌ 缺少 container
// 错误:遗漏 container
const graph = new Graph({});
// 正确:container 必填
const graph = new Graph({ container: 'container' });
❌ 连接桩未设置 magnet
// 错误:端口无法连线
ports: {
items: [{ id: 'port1', group: 'out' }],
groups: {
out: { position: 'right', attrs: { circle: { r: 5 } } }
}
}
// 正确:设置 magnet: true
ports: {
items: [{ id: 'port1', group: 'out' }],
groups: {
out: { position: 'right', attrs: { circle: { r: 5, magnet: true, stroke: '#8f8f8f' } } }
}
}
❌ 事件回调使用位置参数
// 错误:参数不是位置传递
graph.on('node:click', (node, e) => { ... });
// 正确:解构对象参数
graph.on('node:click', ({ node, e }) => { ... });
基础结构模板
import { Graph } from '@antv/x6';
const graph = new Graph({
container: 'container',
background: { color: '#F2F7FA' },
});
const source = graph.addNode({
shape: 'rect',
x: 40,
y: 40,
width: 100,
height: 40,
label: 'Source',
attrs: {
body: { stroke: '#8f8f8f', strokeWidth: 1, fill: '#fff', rx: 6, ry: 6 },
},
});
const target = graph.addNode({
shape: 'rect',
x: 300,
y: 200,
width: 100,
height: 40,
label: 'Target',
attrs: {
body: { stroke: '#8f8f8f', strokeWidth: 1, fill: '#fff', rx: 6, ry: 6 },
},
});
graph.addEdge({
source,
target,
attrs: {
line: { stroke: '#8f8f8f', strokeWidth: 1 },
},
});
// 内容居中:所有节点/边添加完成后调用,使画布内容相对于容器居中显示
// 如需缩放以适应容器,使用 graph.zoomToFit({ padding: 20, maxScale: 1 }) 替代
graph.centerContent();
场景选择指南
| 场景 | 推荐配置 | 关键特性 |
|---|---|---|
| DAG 数据管道 | ports + orth router + connecting | 有向无环、端口连线 |
| ER 实体关系图 | HTML 节点 + er router | 表格式节点、字段展示 |
| 流程图/审批流 | 菱形判断节点 + 分支边 | 条件分支、多路径 |
| 组织架构图 | orth router + 树形布局 | 层级关系、折叠 |
| 血缘分析 | 左右布局 + smooth connector | 多层流转、端口 |
| 网络拓扑 | 圆形节点 + 星型结构 | 设备类型、连接状态 |
| 状态机 | 圆形节点 + 边标签 | 状态转换、事件触发 |
内置节点类型
| shape | 形状 | 适用场景 |
|---|---|---|
rect | 矩形 | 通用节点、流程步骤 |
circle | 圆形 | 状态节点、端点 |
ellipse | 椭圆 | 通用强调 |
polygon | 多边形 | 菱形(判断)、六边形 |
text | 纯文本 | 标注、注释 |
image | 图片 | 图标节点 |
html | HTML | 富文本、表格式节点 |
路由器与连接器
路由器(Router)— 决定边的路径走向
| 类型 | 效果 | 适用场景 |
|---|---|---|
normal | 直线(默认) | 简单图 |
orth | 正交折线 | 流程图、DAG |
manhattan | 智能正交(绕障) | 复杂布局 |
metro | 地铁线风格 | 地铁图 |
er | ER 图专用 | 实体关系图 |
连接器(Connector)— 决定边的线条样式
| 类型 | 效果 | 适用场景 |
|---|---|---|
normal | 直线段(默认) | 简单图 |
rounded | 圆角折线 | 流程图(推荐) |
smooth | 贝塞尔曲线 | 血缘图、关系图 |
jumpover | 跨线跳跃 | 复杂交叉 |
插件速查
| 插件 | 注册方式 | 功能 |
|---|---|---|
| Selection | graph.use(new Selection({ enabled: true, rubberband: true })) | 框选节点 |
| Snapline | graph.use(new Snapline({ enabled: true })) | 对齐辅助线 |
| History | graph.use(new History({ enabled: true })) | 撤销/重做 |
| Clipboard | graph.use(new Clipboard({ enabled: true })) | 复制/粘贴 |
| Keyboard | graph.use(new Keyboard({ enabled: true })) | 快捷键绑定 |
| Scroller | graph.use(new Scroller({ enabled: true })) | 滚动画布 |
| MiniMap | graph.use(new MiniMap({ enabled: true, container })) | 小地图导航 |
| Transform | graph.use(new Transform({ resizing: { enabled: true }, rotating: { enabled: true } })) | 节点缩放/旋转 |
| Export | graph.use(new Export()) | 导出 PNG/SVG |
| Stencil | graph.use(new Stencil({ target: graph, groups: [...] })) | 侧边栏拖拽面板 |
| Dnd | graph.use(new Dnd({ target: graph })) | 拖拽创建节点 |
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/antvis/chart-visualization-skills/antv-x6-editor">View antv-x6-editor on skillZs</a>