先上几个网址
AntV | 蚂蚁数据可视化
AntV X6 图编辑引擎
AntV X6文档
AntV X6 API
AntV X6图表示例
上面是一些用到的网址,先说下我项目中的需求,就是要自己绘制出一个我们想要的图,组态化呈现出来,然后这个图中会有很多节点,每个节点都会有自己的状态 ,状态会实时改变,状态变化的时候,对应的节点标签颜色等都要跟随变化。
那么我们该用什么绘制呢,绘制出来还要符合我们的业务需求,说白了就是要很灵活,想改什么,想用什么节点(自定义图片等),想绑定什么属性等等,我们都可以很灵活的实现。所以就基于AntV X6 来实现这么个事儿。
那么整体的思路就是基于AntV X6来实现这么一个工具,然后它最终是可以将我们绘制的图(节点、路径等)转为一个JSON数据,我们把这个JSON数据转递给后端,后端会实时去改变JSON数据中的具体的某些字段的值(注意不要修改JSON数据的结构),然后再返回给前端,前端会通过AntV X6将这个JSON数据在对应的页面中再渲染出来,每当JSON数据更新就实时更新来实现这么个需求
先看下最终开发实现出的这个效果图:
左边是我们的节点,就上图所示,上面是一些内置的基础的节点,下面是根据自己具体的业务需求自定义的一些图片节点,当然还要其他的一些很多,官网上都有对应示例文档,可以根据自己的需求、业务场景定制。中间就是我们操作的画板,上面是一些小工具,核心就是用到上面的 toJSON 可以将我们绘制的节点路径样式转为JSON,然后右边就是一些属性,当我们点击网格、点击节点、点击线在右侧都会有不同的属性,当然这些属性也都是自己加上的,还有很多属性都可以自定义加上,包括样式属性,节点的边框粗细、颜色,填充色,连接线的样式、动画、路由方式、连接方式、还有节点连接桩等等都是可以设置的
下面介绍下AntV\X6使用
这里只能说是说一些大致的思路方向,核心代码,很多细节不可能都能说到,尤其是右边的具体的属性,我也会将完整代码上传一下
这里是demo完整代码(同样的功能,分别用Vue2、Vue3实现):
基于Vue2+element-ui+AntV X6实现的流程图编辑器
基于Vue3+ts+AntV X6实现的流程图编辑器
1. 安装
# npm
$ npm install @antv/x6 --save
$ npm install insert-css
# yarn
$ yarn add @antv/x6
$ yarn add insert-css
2. 安装完成之后,使用 import 或 require 进行引用
import {Graph, Addon, FunctionExt, Shape} from '@antv/x6'
3. 布局
布局其实蛮简单的了,就正常布局即可
index.vue
<template>
<div class="flow">
<div class="content">
<!--左侧工具栏-->
<div id="stencil" />
<div class="panel">
<!--流程图工具栏-->
<div class="toolbar">
<!-- <tool-bar v-if="isReady" /> -->
</div>
<!--流程图画板-->
<div id="container" />
</div>
<!--右侧工具栏-->
<div class="config">
<!-- <config-panel v-if="isReady" /> -->
</div>
</div>
</div>
</template>
index.css
.flow {
width: 100vw;
height: 100vh;
}
.content {
width: 100%;
height: 100%;
display: flex;
}
#stencil {
width: 290px;
height: 100%;
position: relative;
border-right: 1px solid rgba(0, 0, 0, 0.08);
box-sizing: border-box;
}
.panel {
width: calc(100% - 580px);
height: 100%;
}
.panel .toolbar {
width: 100%;
height: 38px;
display: flex;
align-items: center;
background-color: #f7f9fb;
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.panel #container {
width: 100%;
height: calc(100% - 38px);
}
.config {
width: 290px;
height: 100%;
padding: 0 10px;
border-left: 1px solid rgba(0, 0, 0, 0.08);
box-sizing: border-box;
}
4. 初始化流程图、画板
graph/index.js
this.graph = new Graph({
background: {
color: '#a5a5a5' // 设置画布背景颜色
},
container: dom, //画板的dom容器
width: width, //画板的宽度
height: height, //画板的高度
autoResize: true,
grid: {
size: 10,
visible: true,
type: 'doubleMesh',
args: [
{
color: '#cccccc',
thickness: 1,
},
{
color: '#5F95FF',
thickness: 1,
factor: 4,
},
],
},
scroller: {
enabled: false,
pageVisible: false,
pageBreak: false,
pannable: false,
},
// 开启画布缩放
mousewheel: {
enabled: true,
modifiers: ['ctrl', 'meta'],
minScale: 0.5,
maxScale: 2,
},
connecting: {
anchor: 'center',
connectionPoint: 'anchor',
allowBlank: true,
highlight: true,
snap: true, // 是否自动吸附
allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
allowNode: false, // 是否允许边链接到节点(非节点上的链接桩)
allowBlank: false, // 是否允许连接到空白点
allowLoop: false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点,
allowEdge: false, // 是否允许边链接到另一个边
highlight: true, // 拖动边时,是否高亮显示所有可用的连接桩或节点
connectionPoint: "anchor", // 指定连接点
anchor: "center", // 指定被连接的节点的锚点
createEdge() {
// X6 的 Shape 命名空间中内置 Edge、DoubleEdge、ShadowEdge 三种边
return new Shape.DoubleEdge({
attrs: {
// line: {
// // stroke: '#5F95FF',
// // strokeWidth: 4,
// // targetMarker: {
// // name: 'classic',
// // size: 8,
// // },
// stroke: '#1890ff',
// strokeDasharray: 5,
// targetMarker: null,//block classic diamond cross async path circle circlePlus ellipse
// style: {
// animation: 'ant-line 30s infinite linear',
// },
// },
line: {
strokeWidth: 8,
stroke: '#e54033',
strokeDasharray: 5,
style: {
animation: 'ant-line 30s infinite linear',
},
targetMarker: null, // 去掉箭头
},
outline: {
stroke: '#73d13d',
strokeWidth: 15,
}
},
router: {
name: 'metro',
}
})
},
validateConnection({
sourceView,
targetView,
sourceMagnet,
targetMagnet,
}) {
if (sourceView === targetView) {
return false
}
if (!sourceMagnet) {
return false
}
if (!targetMagnet) {
return false
}
return true
},
},
highlighting: {
magnetAvailable: {
name: 'stroke',
args: {
padding: 4,
attrs: {
strokeWidth: 4,
stroke: 'rgba(223,234,255)',
},
},
},
},
// 开启拖拽平移(防止冲突,按下修饰键并点击鼠标才能触发画布拖拽)
panning: {
enabled: true,
modifiers: 'shift',
},
resizing: true,
rotating: true,
selecting: {
enabled: true,
multiple: true,
rubberband: true,
movable: true,
showNodeSelectionBox: true,
},
snapline: true,
history: true,
clipboard: {
enabled: true,
},
keyboard: {
enabled: true,
},
embedding: {
enabled: true,
findParent({ node }) {
const bbox = node.getBBox()
return this.getNodes().filter((node) => {
// 只有 data.parent 为 true 的节点才是父节点
const data = node.getData()
if (data && data.parent) {
const targetBBox = node.getBBox()
return bbox.isIntersectWithRect(targetBBox)
}
return false
})
},
},
})
5. 初始化左侧根节点
graph/index.js
this.stencil = new Addon.Stencil({
target: this.graph, // 刚才初始化流程图画板的实例
stencilGraphWidth: 280,
search: { rect: true },
collapsable: true,
groups: [
{
name: 'basic',
title: '基础节点',
graphHeight: 180,
},
{
name: 'custom-image',
title: '系统设计图',
graphHeight: 600
},
// {
// name: 'combination',
// title: '组合节点',
// layoutOptions: {
// columns: 1,
// marginX: 60,
// },
// graphHeight: 260,
// },
// {
// name: 'group',
// title: '节点组',
// graphHeight: 100,
// layoutOptions: {
// columns: 1,
// marginX: 60,
// },
// },
],
})
const stencilContainer = document.querySelector('#stencil') // 左侧的节点容器
stencilContainer?.appendChild(this.stencil.container) // 追加进去
6. 初始化具体每个根节点下不同类型节点
① 连接桩配置
ports.js
export const basicPorts = {
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',
}
]
}
export const customPorts = {
groups: {
top: {
position: {
name: 'absolute',
}
},
right: {
position: {
name: 'absolute',
}
},
bottom: {
position: {
name: 'absolute',
}
},
left: {
position: {
name: 'absolute',
}
}
},
items: [
{
id: 'port1',
group: 'top',
// 通过 args 指定绝对位置
args: {
x: 25,
y: -5,
},
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
},
},
},
},
{
id: 'port2',
group: 'right',
args: {
x: 55,
y: 25,
},
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
}
},
}
},
{
id: 'port3',
group: 'bottom',
args: {
x: 25,
y: 55,
},
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
}
}
}
},
{
id: 'port4',
group: 'left',
args: {
x: -5,
y: 25,
},
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
}
}
}
}
]
}
② 注册节点
先注册节点,一会儿再createNode,最后再load
shape.js
import { Graph, Dom, Node } from '@antv/x6'
import { basicPorts, customPorts } from './ports' // 连接桩配置
// 基础节点
export const FlowChartRect = Graph.registerNode('flow-chart-rect', {
inherit: 'rect',
width: 80,
height: 42,
attrs: {
body: {
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#ffffff',
},
fo: {
refWidth: '100%',
refHeight: '100%',
},
foBody: {
xmlns: Dom.ns.xhtml,
style: {
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
},
'edit-text': {
contenteditable: 'true',
class: 'x6-edit-text',
style: {
width: '100%',
textAlign: 'center',
fontSize: 12,
color: 'rgba(0,0,0,0.85)',
},
},
text: {
fontSize: 12,
fill: '#080808',
},
},
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'text',
selector: 'text',
},
{
tagName: 'foreignObject',
selector: 'fo',
children: [
{
ns: Dom.ns.xhtml,
tagName: 'body',
selector: 'foBody',
children: [
{
tagName: 'div',
selector: 'edit-text',
},
],
},
],
},
],
ports: { ...basicPorts },
})
// 组合节点
export const FlowChartImageRect = Graph.registerNode('flow-chart-image-rect', {
inherit: 'rect',
width: 200,
height: 60,
attrs: {
body: {
stroke: '#5F95FF',
strokeWidth: 1,
fill: 'rgba(95,149,255,0.05)',
},
image: {
'xlink:href':
'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
width: 16,
height: 16,
x: 12,
y: 12,
},
title: {
text: 'Node',
refX: 40,
refY: 14,
fill: 'rgba(0,0,0,0.85)',
fontSize: 12,
'text-anchor': 'start',
},
text: {
text: 'this is content text',
refX: 40,
refY: 38,
fontSize: 12,
fill: 'rgba(0,0,0,0.6)',
'text-anchor': 'start',
},
},
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'image',
selector: 'image',
},
{
tagName: 'text',
selector: 'title',
},
{
tagName: 'text',
selector: 'text',
},
],
ports: { ...basicPorts },
})
export const FlowChartTitleRect = Graph.registerNode('flow-chart-title-rect', {
inherit: 'rect',
width: 200,
height: 68,
attrs: {
body: {
stroke: '#5F95FF',
strokeWidth: 1,
fill: 'rgba(95,149,255,0.05)',
},
head: {
refWidth: '100%',
stroke: 'transparent',
height: 28,
fill: 'rgb(95,149,255)',
},
image: {
'xlink:href':
'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
height: 16,
x: 6,
y: 6,
},
title: {
text: 'Node',
refX: 30,
refY: 9,
fill: '#ffffff',
fontSize: 12,
'text-anchor': 'start',
},
text: {
text: 'this is content text',
refX: 8,
refY: 45,
fontSize: 12,
fill: 'rgba(0,0,0,0.6)',
'text-anchor': 'start',
},
},
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'rect',
selector: 'head',
},
{
tagName: 'image',
selector: 'image',
},
{
tagName: 'text',
selector: 'title',
},
{
tagName: 'text',
selector: 'text',
},
],
ports: { ...basicPorts },
})
export const FlowChartAnimateText = Graph.registerNode('flow-chart-animate-text', {
inherit: 'rect',
width: 200,
height: 60,
attrs: {
body: {
stroke: '#5F95FF',
strokeWidth: 1,
fill: 'rgba(95,149,255,0.05)',
},
text1: {
class: 'animate-text1',
text: 'AntV X6',
fontSize: 32,
},
text2: {
class: 'animate-text2',
text: 'AntV X6',
fontSize: 32,
},
},
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'text',
selector: 'text1',
},
{
tagName: 'text',
selector: 'text2',
},
],
})
// 自定义 系统设计图
export const FlowChartImageRectCustom = Graph.registerNode('flow-chart-image-rect-custom', {
inherit: 'rect',
width: 80,
height: 80,
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'image',
},
{
tagName: 'text',
selector: 'label',
}
],
attrs: {
body: {
// 节点线的颜色
stroke: 'transparent',
// 背景填充色
fill: 'transparent',
},
// 自定义图片
image: {
width: 60,
height: 60,
refX: 0,
refY: 0,
},
label: {
refX: 3,
refY: 2,
textAnchor: 'left',
textVerticalAnchor: 'top',
fontSize: 12,
fill: 'black',
},
'edit-text': {
contenteditable: 'true',
class: 'x6-edit-text',
style: {
width: '100%',
textAlign: 'center',
fontSize: 12,
color: 'rgba(0,0,0,0.85)'
},
},
text: {
fontSize: 12,
fill: '#080808',
},
},
ports: { ...customPorts },
})
// 节点组
export class NodeGroup extends Node {
collapsed = true
postprocess() {
this.toggleCollapse(true)
}
isCollapsed() {
return this.collapsed
}
toggleCollapse(collapsed) {
const target = collapsed == null ? !this.collapsed : collapsed
if (target) {
this.attr('buttonSign', { d: 'M 1 5 9 5 M 5 1 5 9' })
this.resize(200, 40)
} else {
this.attr('buttonSign', { d: 'M 2 5 8 5' })
this.resize(240, 240)
}
this.collapsed = target
}
}
NodeGroup.config({
shape: 'rect',
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'image',
selector: 'image',
},
{
tagName: 'text',
selector: 'text',
},
{
tagName: 'g',
selector: 'buttonGroup',
children: [
{
tagName: 'rect',
selector: 'button',
attrs: {
'pointer-events': 'visiblePainted',
},
},
{
tagName: 'path',
selector: 'buttonSign',
attrs: {
fill: 'none',
'pointer-events': 'none',
},
},
],
},
],
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
strokeWidth: 1,
fill: 'rgba(95,149,255,0.05)',
stroke: '#5F95FF',
},
image: {
'xlink:href':
'https://gw.alipayobjects.com/mdn/rms_0b51a4/afts/img/A*X4e0TrDsEiIAAAAAAAAAAAAAARQnAQ',
width: 16,
height: 16,
x: 8,
y: 12,
},
text: {
fontSize: 12,
fill: 'rgba(0,0,0,0.85)',
refX: 30,
refY: 15,
},
buttonGroup: {
refX: '100%',
refX2: -25,
refY: 13,
},
button: {
height: 14,
width: 16,
rx: 2,
ry: 2,
fill: '#f5f5f5',
stroke: '#ccc',
cursor: 'pointer',
event: 'node:collapse',
},
buttonSign: {
refX: 3,
refY: 2,
stroke: '#808080',
},
},
})
Graph.registerNode('groupNode', NodeGroup)
③ createNode、load
graph/index.js
const { graph } = this
// 基础节点
const r1 = graph.createNode({
shape: 'flow-chart-rect',
attrs: {
body: {
rx: 24,
ry: 24,
},
text: {
text: '起始节点',
},
},
})
const r2 = graph.createNode({
shape: 'flow-chart-rect',
attrs: {
text: {
text: '流程节点',
},
},
})
const r3 = graph.createNode({
shape: 'flow-chart-rect',
width: 52,
height: 52,
angle: 45,
attrs: {
'edit-text': {
style: {
transform: 'rotate(-45deg)',
},
},
text: {
text: '判断节点',
transform: 'rotate(-45deg)',
},
},
ports: {
groups: {
top: {
position: {
name: 'top',
args: {
dx: -26,
},
},
},
right: {
position: {
name: 'right',
args: {
dy: -26,
},
},
},
bottom: {
position: {
name: 'bottom',
args: {
dx: 26,
},
},
},
left: {
position: {
name: 'left',
args: {
dy: 26,
},
},
},
},
},
})
const r4 = graph.createNode({
shape: 'flow-chart-rect',
width: 70,
height: 70,
attrs: {
body: {
rx: 35,
ry: 35,
},
text: {
text: '链接节点',
},
},
})
// 组合节点
const c1 = graph.createNode({
shape: 'flow-chart-image-rect',
})
const c2 = graph.createNode({
shape: 'flow-chart-title-rect',
})
const c3 = graph.createNode({
shape: 'flow-chart-animate-text',
})
// 节点组
const g1 = graph.createNode({
shape: 'groupNode',
attrs: {
text: {
text: 'Group Name',
},
},
data: {
parent: true,
},
})
// 系统设计图
const imgs = [
{
image: require('../../../assets/ldb.png')
},
{
image: require('../../../assets/冷冻泵.png')
},
{
image: require('../../../assets/冷却泵.png')
},
{
image: require('../../../assets/wft1.png')
},
{
image: require('../../../assets/wft2.png')
},
{
image: require('../../../assets/wft3.png')
},
{
image: require('../../../assets/wft4.png')
},
{
image: require('../../../assets/wft5.png')
}
]
const imgNodes = imgs.map(item => {
return graph.createNode({
// shape: 'flow-chart-image-rect-custom',
// attrs: {
// image: {
// 'xlink:href': item.image,
// }
// }
shape: 'image', //可选值:Rect Circle Ellipse Polygon Polyline Path Image HTML TextBlock BorderedImage EmbeddedImage InscribedImage Cylinder
imageUrl: item.image,
attrs: {
image: {
// fill: 'yellow',
},
},
width: 52,
height: 52,
ports: { ...customPorts }
})
})
this.stencil.load([r1, r2, r3, r4], 'basic')
this.stencil.load(imgNodes, 'custom-image')
// this.stencil.load([c1, c2, c3], 'combination')
// this.stencil.load([g1], 'group')
7. 根据json数据渲染
graph/index.js
this.graph.fromJSON(jsonData)
8. 鼠标的一些事件,连接桩的显示时机等
graph/index.js 文章来源:https://www.toymoban.com/news/detail-455099.html
// 连接桩显示时机
showPorts(ports, show) {
for (let i = 0, len = ports.length; i < len; i = i + 1) {
ports[i].style.visibility = show ? 'visible' : 'hidden'
}
}
initEvent() {
const { graph } = this
const container = document.getElementById('container')
graph.on('node:contextmenu', ({ cell, view }) => {
console.log(view.container)
const oldText = cell.attr('text/text')
cell.attr('text/style/display', 'none')
const elem = view.container.querySelector('.x6-edit-text')
if (elem) {
elem.innerText = oldText
elem.focus()
}
const onBlur = () => {
cell.attr('text/text', elem.innerText)
}
if(elem){
elem.addEventListener('blur', () => {
onBlur()
elem.removeEventListener('blur', onBlur)
})
}
})
// 鼠标移入 显示连接桩
graph.on('node:mouseenter', FunctionExt.debounce(() => {
const ports = container.querySelectorAll('.x6-port-body')
this.showPorts(ports, true)
}), 500,)
// 鼠标移出 隐藏连接桩
graph.on('node:mouseleave', () => {
const ports = container.querySelectorAll('.x6-port-body')
this.showPorts(ports, false)
})
graph.on('node:collapse', ({ node, e }) => {
e.stopPropagation()
node.toggleCollapse()
const collapsed = node.isCollapsed()
const cells = node.getDescendants()
cells.forEach(n => {
if (collapsed) {
n.hide()
} else {
n.show()
}
})
})
// backspace
graph.bindKey('delete', () => {
const cells = graph.getSelectedCells()
if (cells.length) {
graph.removeCells(cells)
}
})
}
9. 最后再给大家上个导出的JSON数据
export default {
"cells": [
{
"position": {
"x": 420,
"y": 160
},
"size": {
"width": 80,
"height": 42
},
"attrs": {
"text": {
"text": "起始节点"
},
"body": {
"rx": 24,
"ry": 24
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": "top",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": "right",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": "bottom",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": "left",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "45726225-0a03-409e-8475-07da4b8533c5"
},
{
"group": "right",
"id": "06111939-bf01-48d9-9f54-6465d9d831c6"
},
{
"group": "bottom",
"id": "6541f8dc-e48b-4b8c-a105-2ab3a47f1f21"
},
{
"group": "left",
"id": "54781206-573f-4982-a21e-5fac1e0e8a60"
}
]
},
"id": "8650a303-3568-4ff2-9fac-2fd3ae7e6f2a",
"zIndex": 1
},
{
"position": {
"x": 420,
"y": 250
},
"size": {
"width": 80,
"height": 42
},
"attrs": {
"text": {
"text": "流程节点"
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": "top",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": "right",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": "bottom",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": "left",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "d1346f43-969a-4201-af5d-d09b7ef79980"
},
{
"group": "right",
"id": "d561926a-3a24-449a-abb1-0c20bc89947e"
},
{
"group": "bottom",
"id": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
},
{
"group": "left",
"id": "2fceb955-f7af-41ac-ac02-5a2ea514544e"
}
]
},
"id": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
"zIndex": 2
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
},
"strokeDasharray": 0
}
},
"id": "00f3c401-8bad-46b9-b692-232aa011d4c5",
"router": {
"name": "manhattan"
},
"zIndex": 3,
"source": {
"cell": "8650a303-3568-4ff2-9fac-2fd3ae7e6f2a",
"port": "6541f8dc-e48b-4b8c-a105-2ab3a47f1f21"
},
"target": {
"cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
"port": "d1346f43-969a-4201-af5d-d09b7ef79980"
}
},
{
"position": {
"x": 425,
"y": 371
},
"size": {
"width": 70,
"height": 70
},
"attrs": {
"text": {
"text": "链接节点"
},
"body": {
"rx": 35,
"ry": 35
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": "top",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": "right",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": "bottom",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": "left",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "089ce61a-4b17-4ed8-9c3f-5b905f484425"
},
{
"group": "right",
"id": "fd4b8c95-d1eb-41ea-b3e1-15135814b292"
},
{
"group": "bottom",
"id": "9bb8ec19-b1e2-432d-8735-b008da064948"
},
{
"group": "left",
"id": "fbf8759a-1059-47bb-b556-f0a4477e48d3"
}
]
},
"id": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
"zIndex": 4
},
{
"angle": 45,
"position": {
"x": 310,
"y": 380
},
"size": {
"width": 52,
"height": 52
},
"attrs": {
"text": {
"text": "判断节点",
"transform": "rotate(-45deg)"
},
"edit-text": {
"style": {
"transform": "rotate(-45deg)"
}
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": {
"name": "top",
"args": {
"dx": -26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": {
"name": "right",
"args": {
"dy": -26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": {
"name": "bottom",
"args": {
"dx": 26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": {
"name": "left",
"args": {
"dy": 26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
},
{
"group": "right",
"id": "af190d15-b0f1-4f92-85bc-e0c4df83e2a7"
},
{
"group": "bottom",
"id": "c51a4f3b-759b-47ed-9d80-fa4f6c114e64"
},
{
"group": "left",
"id": "c241a7e4-12d3-4dde-9694-0f0e5f7b9a91"
}
]
},
"id": "ef3865af-8a91-4164-8466-3f6b4315070f",
"zIndex": 5
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "9031a1ee-8deb-4b1e-90e6-96d40d3a8515",
"router": {
"name": "manhattan"
},
"zIndex": 7,
"source": {
"cell": "ef3865af-8a91-4164-8466-3f6b4315070f",
"port": "af190d15-b0f1-4f92-85bc-e0c4df83e2a7"
},
"target": {
"cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
"port": "fbf8759a-1059-47bb-b556-f0a4477e48d3"
}
},
{
"angle": 45,
"position": {
"x": 566,
"y": 380
},
"size": {
"width": 52,
"height": 52
},
"attrs": {
"text": {
"text": "判断节点",
"transform": "rotate(-45deg)"
},
"edit-text": {
"style": {
"transform": "rotate(-45deg)"
}
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": {
"name": "top",
"args": {
"dx": -26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": {
"name": "right",
"args": {
"dy": -26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": {
"name": "bottom",
"args": {
"dx": 26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": {
"name": "left",
"args": {
"dy": 26
}
},
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
},
{
"group": "right",
"id": "af190d15-b0f1-4f92-85bc-e0c4df83e2a7"
},
{
"group": "bottom",
"id": "c51a4f3b-759b-47ed-9d80-fa4f6c114e64"
},
{
"group": "left",
"id": "c241a7e4-12d3-4dde-9694-0f0e5f7b9a91"
}
]
},
"id": "9be960d0-fb75-49b1-8131-abc05b5991bd",
"zIndex": 9
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "8af8b072-dfb9-458a-b15e-dd5d4c1863bd",
"router": {
"name": "manhattan"
},
"zIndex": 10,
"source": {
"cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
"port": "d561926a-3a24-449a-abb1-0c20bc89947e"
},
"target": {
"cell": "9be960d0-fb75-49b1-8131-abc05b5991bd",
"port": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
}
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "58874c23-da0b-46e6-9124-5154e8570bfd",
"router": {
"name": "manhattan"
},
"zIndex": 11,
"source": {
"cell": "9be960d0-fb75-49b1-8131-abc05b5991bd",
"port": "c241a7e4-12d3-4dde-9694-0f0e5f7b9a91"
},
"target": {
"cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
"port": "fd4b8c95-d1eb-41ea-b3e1-15135814b292"
}
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "13d78262-f889-4e6f-9980-29f9e2d87c8f",
"router": {
"name": "manhattan"
},
"zIndex": 12,
"source": {
"cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
"port": "2fceb955-f7af-41ac-ac02-5a2ea514544e"
},
"target": {
"cell": "ef3865af-8a91-4164-8466-3f6b4315070f",
"port": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
}
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "9c7b7539-2f82-478d-a592-60dfceede791",
"router": {
"name": "manhattan"
},
"zIndex": 13,
"source": {
"cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
"port": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
},
"target": {
"cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
"port": "089ce61a-4b17-4ed8-9c3f-5b905f484425"
}
},
{
"position": {
"x": 420,
"y": 497
},
"size": {
"width": 80,
"height": 42
},
"attrs": {
"text": {
"text": "流程节点"
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": "top",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": "right",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": "bottom",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": "left",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "d1346f43-969a-4201-af5d-d09b7ef79980"
},
{
"group": "right",
"id": "d561926a-3a24-449a-abb1-0c20bc89947e"
},
{
"group": "bottom",
"id": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
},
{
"group": "left",
"id": "2fceb955-f7af-41ac-ac02-5a2ea514544e"
}
]
},
"id": "c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5",
"zIndex": 14
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "9dfeb591-70e1-4b52-a463-3078a6fde579",
"router": {
"name": "manhattan"
},
"zIndex": 15,
"source": {
"cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
"port": "9bb8ec19-b1e2-432d-8735-b008da064948"
},
"target": {
"cell": "c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5",
"port": "d1346f43-969a-4201-af5d-d09b7ef79980"
}
},
{
"position": {
"x": 420,
"y": 616
},
"size": {
"width": 80,
"height": 42
},
"attrs": {
"text": {
"text": "结束节点"
},
"body": {
"rx": 24,
"ry": 24
}
},
"visible": true,
"shape": "flow-chart-rect",
"ports": {
"groups": {
"top": {
"position": "top",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"right": {
"position": "right",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"bottom": {
"position": "bottom",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
},
"left": {
"position": "left",
"attrs": {
"circle": {
"r": 3,
"magnet": true,
"stroke": "#5F95FF",
"strokeWidth": 1,
"fill": "#fff",
"style": {
"visibility": "hidden"
}
}
}
}
},
"items": [
{
"group": "top",
"id": "45726225-0a03-409e-8475-07da4b8533c5"
},
{
"group": "right",
"id": "06111939-bf01-48d9-9f54-6465d9d831c6"
},
{
"group": "bottom",
"id": "6541f8dc-e48b-4b8c-a105-2ab3a47f1f21"
},
{
"group": "left",
"id": "54781206-573f-4982-a21e-5fac1e0e8a60"
}
]
},
"id": "5ac48b64-d507-4006-954b-f8fbf8016ad2",
"zIndex": 16
},
{
"shape": "edge",
"attrs": {
"line": {
"stroke": "#5F95FF",
"strokeWidth": 1,
"targetMarker": {
"name": "classic",
"size": 8
}
}
},
"id": "f847f055-9073-4c8e-92c5-8124597d1e7e",
"router": {
"name": "manhattan"
},
"zIndex": 17,
"source": {
"cell": "c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5",
"port": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
},
"target": {
"cell": "5ac48b64-d507-4006-954b-f8fbf8016ad2",
"port": "45726225-0a03-409e-8475-07da4b8533c5"
}
}
]
}
以上都是核心代码了,希望帮到大家! 文章来源地址https://www.toymoban.com/news/detail-455099.html
到了这里,关于Vue使用AntV X6绘制流程图(组态呈现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!