<template>
<div class="x6-content">
<div id="stencil"></div>
<div id="graph-container"></div>
</div>
</template>
<script>
import { Graph, Shape, Addon } from "@antv/x6";
export default {
data() {
return {
graph: null,
// 初始化图形
ports: {
groups: {
top: {
position: "top",
attrs: {
circle: {
r: 4,
magnet: true,
stroke: "#5F95FF",
strokeWidth: 1,
fill: "#fff",
style: {
visibility: "hidden",
},
},
},
},
right: {
position: "right",
attrs: {
circle: {
r: 4,
magnet: true,
stroke: "#5F95FF",
strokeWidth: 1,
fill: "#fff",
style: {
visibility: "hidden",
},
},
},
},
bottom: {
position: "bottom",
attrs: {
circle: {
r: 4,
magnet: true,
stroke: "#5F95FF",
strokeWidth: 1,
fill: "#fff",
style: {
visibility: "hidden",
},
},
},
},
left: {
position: "left",
attrs: {
circle: {
r: 4,
magnet: true,
stroke: "#5F95FF",
strokeWidth: 1,
fill: "#fff",
style: {
visibility: "hidden",
},
},
},
},
},
items: [
{
group: "top",
},
{
group: "right",
},
{
group: "bottom",
},
{
group: "left",
},
],
},
};
},
mounted() {
this.initData();
},
methods: {
initData() {
// #region 初始化画布
this.graph = new Graph({
container: document.getElementById("graph-container"),
grid: true,
mousewheel: {
enabled: true,
zoomAtMousePosition: true,
modifiers: "ctrl",
minScale: 0.5,
maxScale: 3,
},
connecting: {
router: {
name: "manhattan",
args: {
padding: 1,
},
},
connector: {
name: "rounded",
args: {
radius: 8,
},
},
anchor: "center",
connectionPoint: "anchor",
allowBlank: false,
snap: {
radius: 20,
},
createEdge() {
return new Shape.Edge({
attrs: {
line: {
stroke: "#A2B1C3",
strokeWidth: 2,
targetMarker: {
name: "block",
width: 12,
height: 8,
},
},
},
zIndex: 0,
});
},
validateConnection({ targetMagnet }) {
return !!targetMagnet;
},
},
highlighting: {
magnetAdsorbed: {
name: "stroke",
args: {
attrs: {
fill: "#5F95FF",
stroke: "#5F95FF",
},
},
},
},
resizing: true,
rotating: true,
selecting: {
enabled: true,
rubberband: true,
showNodeSelectionBox: true,
},
snapline: true,
keyboard: true,
clipboard: true,
});
// #endregion
// #region 初始化 stencil
const stencil = new Addon.Stencil({
title: "流程图",
target: this.graph,
stencilGraphWidth: 200,
stencilGraphHeight: 180,
collapsable: true,
groups: [
{
title: "基础流程图",
name: "group1",
},
],
layoutOptions: {
columns: 2,
columnWidth: 80,
rowHeight: 55,
},
});
document.getElementById("stencil").appendChild(stencil.container);
// #region 快捷键与事件
this.shortCutKeyPractice(this.graph);
// 控制连接桩显示/隐藏
this.operatePorts(this.graph);
// #region 初始化图形
Graph.registerNode(
"custom-rect",
{
inherit: "rect",
width: 66,
height: 36,
attrs: {
body: {
strokeWidth: 1,
stroke: "#5F95FF",
fill: "#EFF4FF",
},
text: {
fontSize: 12,
fill: "#262626",
},
},
tools: [
{
name: "button-remove",
arg: { x: -6, y: -8 },
},
],
ports: { ...this.ports },
},
true
);
const r1 = this.graph.createNode({
shape: "custom-rect",
label: "开始",
attrs: {
body: {
rx: 20,
ry: 26,
},
},
});
stencil.load([r1], "group1");
},
shortCutKeyPractice(graph) {
// copy cut paste
graph.bindKey(["meta+c", "ctrl+c"], () => {
const cells = graph.getSelectedCells();
if (cells.length) {
graph.copy(cells);
}
return false;
});
graph.bindKey(["meta+x", "ctrl+x"], () => {
const cells = graph.getSelectedCells();
if (cells.length) {
graph.cut(cells);
}
return false;
});
graph.bindKey(["meta+v", "ctrl+v"], () => {
if (!graph.isClipboardEmpty()) {
const cells = graph.paste({ offset: 32 });
graph.cleanSelection();
graph.select(cells);
}
return false;
});
//undo redo
graph.bindKey(["meta+z", "ctrl+z"], () => {
if (graph.history.canUndo()) {
graph.history.undo();
}
return false;
});
graph.bindKey(["meta+shift+z", "ctrl+shift+z"], () => {
if (graph.history.canRedo()) {
graph.history.redo();
}
return false;
});
// select all
graph.bindKey(["meta+a", "ctrl+a"], () => {
const nodes = graph.getNodes();
if (nodes) {
graph.select(nodes);
}
});
//双击修改内容
graph.on("cell:dblclick", ({ cell, e }) => {
const isNode = cell.isNode();
const name = cell.isNode() ? "node-editor" : "edge-editor";
cell.removeTool(name);
cell.addTools({
name,
args: {
event: e,
attrs: {
backgroundColor: isNode ? "#EFF4FF" : "#FFF",
},
},
});
});
},
operatePorts(graph) {
// 控制连接桩显示/隐藏
const showPorts = (ports, show) => {
for (let i = 0, len = ports.length; i < len; i = i + 1) {
ports[i].style.visibility = show ? "visible" : "hidden";
}
};
graph.on("node:mouseenter", () => {
const container = document.getElementById("graph-container");
const ports = container.querySelectorAll(".x6-port-body");
showPorts(ports, true);
});
graph.on("node:mouseleave", () => {
const container = document.getElementById("graph-container");
const ports = container.querySelectorAll(".x6-port-body");
showPorts(ports, false);
});
graph.on("edge:mouseenter", ({ edge }) => {
edge.addTools([
"source-arrowhead",
"target-arrowhead",
{
name: "button-remove",
args: {
distance: -30,
},
},
]);
});
graph.on("edge:mouseleave", ({ edge }) => {
edge.removeTools();
});
},
},
};
</script>
<style lang="less" scoped>
.x6-content {
display: flex;
width: 100%;
height: 100%;
#stencil {
width: 200px;
height: 100%;
}
#graph-container {
width: calc(100% - 200px);
height: 100%;
}
}
</style>
x6实现节点新增编辑删除
于 2023-09-03 23:33:07 首次发布
本文介绍了如何使用AntVX6库在网页上创建交互式的流程图,包括图形布局、Stencil组件、节点和边的定义,以及键盘快捷键的绑定和事件操作。
摘要由CSDN通过智能技术生成