JTopo + Vue 实现自定义拖拽流程图
进入体验效果
进入github
市场上做流程图的插件比较多,这里介绍一种基于canvas编写的js插件,结合vue框架做出精美的流程图
首先搭建vue框架,这里就不做介绍,由于jtopo官方demo里用到了jquery,所以我的项目里也引用了jquery插件,鉴于这里用到了很多的dom操作,所以建议大家也直接引用jquery进行操作;
然后将jtopo.js下载到本地,放到自己的vue项目的静态文件目录下,如下图:
最终实现效果如下图
左侧图标采用的是阿里巴巴的iconfont字体图标,需将字体文件下载到本地,具体用法参考https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.17&helptype=code
这里demo使用数据结构为
// node-template.mock.js
export default [{
id: '0',
text: '鼠',
type: 1,
img: `rat.png`,
icon: ''
}, {
id: '1',
text: '牛',
type: 2,
img: `cow.png`,
icon: ''
}, {
id: '2',
text: '虎',
type: 3,
img: `tiger.png`,
icon: ''
}, {
id: '3',
text: '兔',
type: 4,
img: `rabbit.png`,
icon: ''
}, {
id: '4',
text: '龙',
type: 5,
img: `dragon.png`,
icon: ''
}, {
id: '5',
text: '蛇',
type: 6,
img: `snake.png`,
icon: ''
}, {
id: '6',
text: '马',
type: 7,
img: `horse.png`,
icon: ''
}, {
id: '7',
text: '羊',
type: 8,
img: `sheep.png`,
icon: ''
}, {
id: '8',
text: '猴',
type: 9,
img: `monkey.png`,
icon: ''
}, {
id: '9',
text: '鸡',
type: 10,
img: `chicken.png`,
icon: ''
}, {
id: '10',
text: '狗',
type: 11,
img: `dog.png`,
icon: ''
}, {
id: '11',
text: '猪',
type: 12,
img: `pig.png`,
icon: ''
}]
引用及dom渲染
// ListInfo.vue
import NodesTemplate from '../mock/node-template.mock'
<div class="node-template">
<ul>
<template v-for="node in nodesTemplate">
<li :key="node.id" :id="node.id">
<i class="iconfont option-font" v-html="node.icon"></i>
<span>{{node.text}}</span>
</li>
</template>
</ul>
</div>
点击图标事件
$('.node-template').on('mousedown', 'li', function (event) { // 左侧图标列表点击时
let index = $(this).attr('id')
let imgUrl = `./static/lib/img/node/edit/${NodesTemplate[index].img}`
window.vm.newNode = {
nodeType: NodesTemplate[index].type,
nodeName: vm.generateUniqNodeName(NodesTemplate[index].type)
}
let img = $('<img id="testImg" src="' + imgUrl + '" alt="" style="display: none; width: 52px;height: 52px; opacity: 0.5"/>')
$('body').append(img)
let pageX = event.pageX
let pageY = event.pageY
$('#testImg').css({
position: 'absolute',
left: pageX - 20 + 'px',
top: pageY - 20 + 'px'
}).show()
})
// 拖拽图标松开鼠标时判断落点范围是否在画布内
$(document).on('mouseup', function (event) {
event.preventDefault()
let img = $('#testImg')
if (img.length === 1) {
let canvasBox = $('.canvas-box')
let maxX = window.vm.canvasOffset.x + canvasBox.width()
let minX = window.vm.canvasOffset.x
let maxY = window.vm.canvasOffset.y + canvasBox.height()
let minY = window.vm.canvasOffset.y
let pageX = event.pageX
let pageY = event.pageY
if (pageX > minX && pageX < maxX && pageY > minY && pageY < maxY) {
let canvasX = pageX - window.vm.canvasOffset.x - window.vm.scene.translateX
let canvasY = pageY - window.vm.canvasOffset.y - window.vm.scene.translateY
window.vm.newNode['nodeX'] = canvasX
window.vm.newNode['nodeY'] = canvasY
window.vm.newNode['versionId'] = window.vm.version.versionId
window.vm.newNode['nodeOrder'] = ++window.vm.nodeMaxOrder
window.vm.newNode['nodeCode'] = 'ND_' + window.vm.nodeMaxOrder
window.vm.drawNode(window.vm.newNode)
}
img.remove()
}
})
// 左侧图标拖拽事件
$(document).on('mousemove', function (event) {
event.preventDefault()
let img = $('#testImg')
if (img.length === 1) {
let pageX = event.pageX
let pageY = event.pageY
img.css({
position: 'absolute',
left: pageX - 20 + 'px',
top: pageY - 20 + 'px'
})
}
})
节点右键编辑
点击线操作
代码在不断完善中,有不错的建议和意见欢迎提出!