"name"
:
"条件1-1"
,
"source_state_id"
:
6
,
"destination_state_id"
:
5
,
"attribute_type_id"
:
1
"name"
:
"条件2-1"
,
"source_state_id"
:
9
,
"destination_state_id"
:
6
,
"attribute_type_id"
:
1
"name"
:
"条件2-2"
,
"source_state_id"
:
5
,
"destination_state_id"
:
6
,
"attribute_type_id"
:
2
"name"
:
"条件3-1"
,
"source_state_id"
:
10
,
"destination_state_id"
:
9
,
"attribute_type_id"
:
1
"name"
:
"条件3-2"
,
"source_state_id"
:
5
,
"destination_state_id"
:
9
,
"attribute_type_id"
:
2
"name"
:
"条件4-1"
,
"source_state_id"
:
11
,
"destination_state_id"
:
10
,
"attribute_type_id"
:
1
"name"
:
"条件4-2"
,
"source_state_id"
:
5
,
"destination_state_id"
:
10
,
"attribute_type_id"
:
2
"name"
:
"条件5-1"
,
"source_state_id"
:
12
,
"destination_state_id"
:
11
,
"attribute_type_id"
:
1
"name"
:
"条件5-2"
,
"source_state_id"
:
5
,
"destination_state_id"
:
11
,
"attribute_type_id"
:
2
"name"
:
"条件6-1"
,
"source_state_id"
:
13
,
"destination_state_id"
:
12
,
"attribute_type_id"
:
1
"name"
:
"条件6-2"
,
"source_state_id"
:
5
,
"destination_state_id"
:
12
,
"attribute_type_id"
:
2
"name"
:
"条件7-1"
,
"source_state_id"
:
18
,
"destination_state_id"
:
13
,
"attribute_type_id"
:
1
"name"
:
"条件7-2"
,
"source_state_id"
:
5
,
"destination_state_id"
:
13
,
"attribute_type_id"
:
2
"name"
:
"条件8-1"
,
"source_state_id"
:
19
,
"destination_state_id"
:
6
,
"attribute_type_id"
:
3
"name"
:
"条件8-2"
,
"source_state_id"
:
11
,
"destination_state_id"
:
19
,
"attribute_type_id"
:
1
"node_data"
:
[
"id"
:
1
,
"name"
:
"开始"
,
"type_id"
:
1
,
"order_id"
:
1
"id"
:
2
,
"name"
:
"过程1"
,
"type_id"
:
0
,
"order_id"
:
2
"id"
:
3
,
"name"
:
"过程2-1"
,
"type_id"
:
0
,
"order_id"
:
3
"id"
:
4
,
"name"
:
"过程2-2"
,
"type_id"
:
0
,
"order_id"
:
3
"id"
:
5
,
"name"
:
"过程3"
,
"type_id"
:
0
,
"order_id"
:
4
"id"
:
6
,
"name"
:
"过程4"
,
"type_id"
:
0
,
"order_id"
:
5
"id"
:
7
,
"name"
:
"过程5"
,
"type_id"
:
0
,
"order_id"
:
6
"id"
:
8
,
"name"
:
"过程6"
,
"type_id"
:
0
,
"order_id"
:
7
"id"
:
9
,
"name"
:
"结束"
,
"type_id"
:
2
,
"order_id"
:
8
1.antvX6
npm install @antv/x6 --save
2.对齐线
npm install @antv/x6-plugin-snapline --save
html代码
<template>
<div class="info-box">
<div class="top-box"
id="top-width">
<el-button type=""
@click="zoomToFit">填满</el-button>
</div>
<div class="content-box">
<div class="container-box">
<div id="container"></div>
</div>
</div>
</div>
</template>
<script>
import API from '../api'
import { Graph } from '@antv/x6'
import { Snapline } from '@antv/x6-plugin-snapline'
Graph.registerNode(
'custom-rect',
inherit: 'rect',
width: 200,
height: 40,
attrs: {
body: {
strokeWidth: 1,
stroke: '#5F95FF',
fill: '#EFF4FF'
text: {
fontSize: 12,
fill: '#262626'
text: {
fontSize: 12,
fill: '#262626'
export default {
data() {
return {
loading: false,
graph: null,
data: {
nodes: [],
edges: []
mounted() {
this.initGraph()
beforeDestroy() {
this.graph.dispose()
this.graph = null
methods: {
initGraph() {
const container = document.getElementById('container')
this.graph = new Graph({
container: container,
width: container.offsetWidth,
height: container.offsetHeight,
autoResize: true,
background: {
color: '#F2F7FA'
panning: {
enabled: true
mousewheel: {
enabled: true,
modifiers: 'Ctrl',
factor: 1.1,
maxScale: 10,
minScale: 0.05
grid: {
visible: true,
type: 'doubleMesh',
args: [
color: '#eee',
thickness: 1
color: '#ddd',
thickness: 1,
factor: 4
this.graph.use(
new Snapline({
enabled: true
this.graph.on('edge:mouseenter', ({ e, edge, view }) => {
edge.attr({
line: {
stroke
: 'red',
strokeWidth: 3
this.graph.on('edge:mouseleave', ({ edge }) => {
edge.attr({
line: {
stroke: '#8f8f8f',
strokeWidth: 1
init() {
this.loading = true
API.getData().then(res => {
if (res.code === 200) {
this.setGraphData(res)
} else {
this.$message.error(res.msg)
}).finally(() => {
this.loading = false
setGraphData(data) {
const X = 200
this.data = {
nodes: [],
edges: []
const obj = {}
data.node_data.map(item => {
if (obj[item.order_id]) {
obj[item.order_id].push(item)
} else {
obj[item.order_id] = []
obj[item.order_id].push(item)
Object.keys(obj).forEach((key, objIndex) => {
obj[key].map((item, index) => {
const node = {
id: item.id,
shape: 'custom-rect',
label: item.name,
x: X + 300 * index,
y: 40 + 100 * objIndex,
attrs: {
body: {
rx: item.type_id === 0 ? 4 : 10,
ry: item.type_id === 0 ? 4 : 10
this.data.nodes.push(node)
data.line_data.map((item, index) => {
const obj = {
id: item.id,
shape: 'edge',
source: item.destination_state_id,
target: item.source_state_id,
labels: [
attrs: {
label: {
text: item.name
position: 0.4
router: {
name: 'manhattan',
args: {
startDirections: item.attribute_type_id === 1 ? ['bottom'] : item.attribute_type_id === 2 ? ['left'] : ['right'],
endDirections: item.attribute_type_id === 1 ? ['top'] : item.attribute_type_id === 2 ? ['left'] : ['right']
tools: [{
name: 'segments',
args: {
snapRadius: 20,
attrs: {
fill: '#444'
}],
attrs: {
line: {
stroke: '#8f8f8f',
strokeWidth: 1
this.data.edges.push(obj)
this.graph.fromJSON(this.data)
zoomToFit() {
this.graph.zoomToFit({
padding: 20,
preserveAspectRatio: true,
maxScale: 1
</script>
css代码
<style lang="scss" scoped>
.info-box {
position: relative;
width: 100%;
height: 100%;
padding: 1rem;
box-sizing: border-box;
.top-box {
width: 100%;
height: 3rem;
.content-box {
width: 100%;
height: calc(100% - 3rem);
.container-box {
width: 100%;
height: 100%;
</style>
最近公司需要做一个流程图, 看了看antv/X6感觉挺合适,就研究了半个月。 网上也没什么资料,又怕自己忘,就自己记录一下用到得一些事件方法,方便以后再用到可以查阅。
一:实现流程图最重要得就是画布了,官网上都有文档可以轻松实现画布。下面放一下我用VUE写得画布代码。
首先最重要得就是下载依赖了, x6在vue中下载得话需要下载两个依赖;
npm install @antv/x6 --save
npm install @antv/x6-vue-shape
把这两个依赖下载好就可以在vue中使用X6了
先说下我项目中的需求,就是要自己绘制出一个我们想要的图,组态化呈现出来,然后这个图中会有很多节点,每个节点都会有自己的状态,状态会实时改变,状态变化的时候,对应的节点标签颜色等都要跟随变化。
那么我们该用什么绘制呢,绘制出来还要符合我们的业务需求,说白了就是要很灵活,想改什么,想用什么节点(自定义图片等),想绑定什么属性等等,我们都可以很灵活的实现。所以就基于AntV X6 来实现这么个事儿。
本次在React中使用antv X6 2.0的功能包括:1、节点右键菜单;2、节点自动布局;3、根据列表动态渲染节点;4、节点之间的连线;5、模版引用时的预览功能;6、使用拖拽组件添加节点(包含2种样式 及群组的添加);