我们给定一串数据,然后结合数据用 JointJS 在画布中绘制出元素
data.js
export default [{
id: 1,
type: 'start',
name: '事件',
prev: [],
next: [2, 5, 6]
}, {
id: 2,
type: 'field',
name: '字段1',
prev: [1],
next: [4]
}, {
id: 4,
type: 'field',
name: '字段2',
prev: [2],
next: [3]
}, {
id: 5,
type: 'field',
name: '字段3',
prev: [1],
next: [4]
}, {
id: 6,
type: 'field',
name: '字段4',
prev: [1],
next: [4]
}, {
id: 3,
type: 'end',
name: '结束',
prev: [4],
next: []
}]
vue 文件
<template>
<div class="canvas" ref="canvas"></div>
</template>
import {dia, layout, shapes} from 'jointjs'
import dagre from 'dagre'
import graphlib from '@dagrejs/graphlib'
import data from "./data"
export default {
data() {
return {
graph: null,
paper: null,
items: data,
nodeSet: {}
}
},
mounted() {
this.init()
this.render()
},
methods: {
init() {
const canvasRect = this.$refs.canvas.getClientRects()[0]
this.graph = new dia.Graph()
this.paper = new dia.Paper({
el: this.$refs.canvas,
model: this.graph,
width: canvasRect.width,
height: canvasRect.height,
gridSize: 1
})
// See https://resources.jointjs.com/docs/jointjs/v3.3/joint.html#dia.Paper.events
this.paper.on('element:pointerclick', (cell) => {
Object.keys(this.nodeSet).forEach(item => {
if (this.nodeSet[item].id === cell.model.id) {
console.log(item) // 当前点击元素id
console.log(data[item]) // 当前点击元素内容
}
})
})
},
render() {
const {nodes, links, nodeSet} = this
nodes.forEach((node) => {
const option = {
size: {
width: 100,
height: 40
},
attrs: {
body: {
fill: '#ddd',
strokeWidth: 1,
stroke: '#ccc'
},
label: {
text: node.name,
fill: '#333'
}
}
}
let item
if (node.type === 'start' || node.type === 'end') {
item = new shapes.standard.Ellipse(option)
} else {
item = new shapes.standard.Rectangle(option)
}
item.addTo(this.graph)
nodeSet[node.id] = item
})
links.forEach(([from, to]) => {
const link = new shapes.standard.Link({
source: nodeSet[from],
target: nodeSet[to],
attrs: {
line: {
stroke: '#aaa'
}
}
})
link.addTo(this.graph)
})
this.doLayout()
},
doLayout() {
layout.DirectedGraph.layout(this.graph, {
dagre: dagre,
graphlib: graphlib,
setLinkVertices: false,
rankDir: 'LR', //节点方向 有几个选项 "TB" (top-to-bottom) / "BT" (bottom-to-top) / "LR" (left-to-right) / "RL" (right-to-left)
align: 'DL',
rankSep: 50,
marginX: 60,
marginY: 60,
nodeSep: 50,
edgeSep: 20
})
}
},
computed: {
nodes() {
const nodes = []
this.items.forEach(item => {
nodes.push(item)
})
return nodes
},
links() {
const links = []
this.items.forEach(item => {
item.next.forEach(p => {
links.push([item.id, p])
})
})
return links
}
}
}
</script>
效果