joint绘制流程图
首先给个效果图,以防你们点进来发现不是自己想要的东西
这里调试的时候是按手机大小写的,所以看起来有点小,问题不大。
我在这用的是joint工具进行绘制。
第一步当然是安装这个工具,毋庸置疑
npm install jointjs --save
安装完后,别的资料有说要用在main.js里加入
window.$ = require('jquery');
window.joint = require('jointjs');
搞一下全局变量,我没用这个,所以忽略这一步,直接在页面里引用
import * as joint from 'jointjs'
测试数据如下
history: {
1: 1,
2: 1,
3: 1,
4: 9,
5: 1
},
nodes: [
{
id: 1,
name: '流程2',
nodeX: 292,
nodeY: 84
},
{
id: 2,
name: '流程1',
nodeX: 46,
nodeY: 289
},
{
id: 3,
name: '流程3',
nodeX: 292,
nodeY: 465
},
{
id: 4,
name: '流程4',
nodeX: 524,
nodeY: 347
},
{
id: 5,
name: '流程5',
nodeX: 292,
nodeY: 19
},
{
id: 6,
name: '流程6',
nodeX: 292,
nodeY: 231
},
{
id: 7,
name: '流程7',
nodeX: 292,
nodeY: 231
}
],
routes: [
{
fromNodeId: 1,
toNodeId: 2,
toDescribe: '1-2'
},
{
fromNodeId: 2,
toNodeId: 3,
toDescribe: '2-3'
},
{
fromNodeId: 3,
toNodeId: 5,
toDescribe: '3-5'
},
{
fromNodeId: 5,
toNodeId: 4,
toDescribe: '5-4'
},
{
fromNodeId: 4,
toNodeId: 6,
toDescribe: '4-6'
},
{
fromNodeId: 6,
toNodeId: 7,
toDescribe: '6-7'
},
{
fromNodeId: 7,
toNodeId: 1,
toDescribe: '7-1'
}
],
以上是用的数据,就放到data里的return中即可,小伙伴们在写代码需要调用后端数据,可以在mounted里先请求后端接口获取数据
完整代码与注解如下
<template>
<div>
<Button size="small" type="primary" @click="changeSize('big')">
放大
</Button>
<Button size="small" type="primary" @click="changeSize('small')">
缩小
</Button>
<div id="aa"></div>
</div>
</template>
<script>
import * as joint from 'jointjs'
export default {
name: 'About',
components: {},
data() {
return {
history: {},
nodes: [],
routes: [],
// 图
graph: new joint.dia.Graph(),
// 页面
paper: '',
// 宽度
width: document.body.clientWidth,
// 颜色选区
color: ['#ffffff', '#07de62', '#f5f65e', '#ff546c']
}
},
async mounted() {
//我这边是直接用测试数据,要请求后端可以在这加个方法,如下
//这里可以加个loding
//const result = await 服务.方法(传递的数据)
//加载完去除loding
//if (result.data === null) {
// return
//}
//const { history, nodes, routes } = result.data
//调用下面的papers方法
this.paper = this.papers()
// 绘制节点
const nodesList = []
for (const i in this.nodes) {
nodesList.push(
this.rectStatue(
this.nodes[i].nodeX,
this.nodes[i].nodeY,
100,
this.heightNode(this.nodes[i].name).height,
this.heightNode(this.nodes[i].name).text
)
)
this.graph.addCells([nodesList[i]])
}
// 绘制图片
for (const i in this.routes) {
const formIndex = this.nodes.findIndex((item) => {
return item.id === this.routes[i].fromNodeId
})
const toIndex = this.nodes.findIndex((item) => {
return item.id === this.routes[i].toNodeId
})
const link = this.link(
nodesList[formIndex],
nodesList[toIndex],
this.routes[i].toDescribe
)
this.graph.addCells([link])
}
for (const i in this.history) {
const index = this.nodes.findIndex((item) => {
return item.id === Number(i)
})
let num = 0
if (this.history[i] > 3) {
num = 3
} else {
num = this.history[i]
}
nodesList[index].attr({ rect: { fill: this.color[num] } })
}
/**
* 初始化页面的时候找到第一个节点的位置,将画板移动到第一个节点的位置
*/
this.paper.translate(-this.nodes[0].nodeX + this.width / 2, 0)
// 拖动画板移动函数
this.movePaper()
this.changeSize('init')
},
methods: {
/**
* 手指按下的事件拖动画板的移动
* @type {{startMove: number, origin: *, startY: number, startX: number}}
*/
movePaper() {
const self = {
startX: 0,
startY: 0,
origin: this.paper.options.origin,
startMove: 0
}
const that = this
this.paper.on({
'blank:pointerdown': function (evt, x, y) {
self.startX = x
self.startY = y
self.startMove = true
},
'blank:pointermove': function (evt, x, y) {
if (self.startMove) {
var diffX = x - self.startX + self.origin.x
var diffY = y - self.startY + self.origin.y
that.paper.translate(diffX, diffY)
}
},
'blank:pointerup': function (evt, x, y) {
self.startMove = false
}
})
},
changeSize(type) {
const { sy } = this.paper.scale()
if (type === 'big') {
this.paper.scale(sy + 0.1)
console.log((sy + 0.1).toFixed(1) + '倍')
} else if (type === 'small') {
if (sy.toFixed(1) === '0.5') {
console.log('已缩小到最小倍数')
return
}
this.paper.scale(sy - 0.1)
console.log((sy - 0.1).toFixed(1) + '倍')
} else if (type === 'init') {
this.paper.scale(sy - 0.2)
}
},
heightNode(text) {
const breakedText = joint.util.breakText(text, { width: 100 })
const lineNum = breakedText.split('\n').length
return {
height: lineNum === 1 ? lineNum * 30 : lineNum * 20,
text: breakedText
}
},
link(source, target, text) {
return new joint.shapes.standard.Link({
source: { id: source.id },
target: { id: target.id },
labels: [
{
position: 0.5,
attrs: {
text: {
text: text || '',
'font-weight': 'bold',
'font-size': '12px'
}
}
}
],
router: { name: 'manhattan' }
})
},
rectStatue(x, y, width, height, text) {
return new joint.shapes.basic.Rect({
position: { x: x, y: y },
size: { width: width, height: height },
attrs: {
rect: { fill: 'white' },
text: { text: text, fill: 'black' }
}
})
},
papers() {
const ElementView = joint.dia.ElementView.extend({
pointerdown: function () {
this._click = true
joint.dia.ElementView.prototype.pointerdown.apply(this, arguments)
},
pointermove: function (evt, x, y) {
this._click = false
},
pointerup: function (evt, x, y) {
this._click = true
if (this._click) {
this.notify('cell:click', evt, x, y)
} else {
joint.dia.ElementView.prototype.pointerup.apply(this, arguments)
}
}
})
return new joint.dia.Paper({
el: document.getElementById('aa'),
width: document.body.clientWidth,
height: window.innerHeight - 50,
model: this.graph,
gridSize: 1,
elementView: ElementView
})
}
}
}
</script>
<style>
</style>
应该不难看懂,有问题可以在下面留言