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.pageXlet 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.xlet maxY = window.vm.canvasOffset.y + canvasBox.height()let minY = window.vm.canvasOffset.ylet pageX = event.pageXlet pageY = event.pageYif (pageX > minX && pageX < maxX && pageY > minY && pageY < maxY) {let canvasX = pageX - window.vm.canvasOffset.x - window.vm.scene.translateXlet canvasY = pageY - window.vm.canvasOffset.y - window.vm.scene.translateYwindow.vm.newNode['nodeX'] = canvasXwindow.vm.newNode['nodeY'] = canvasYwindow.vm.newNode['versionId'] = window.vm.version.versionIdwindow.vm.newNode['nodeOrder'] = ++window.vm.nodeMaxOrderwindow.vm.newNode['nodeCode'] = 'ND_' + window.vm.nodeMaxOrderwindow.vm.drawNode(window.vm.newNode)}img.remove()}})// 左侧图标拖拽事件$(document).on('mousemove', function (event) {event.preventDefault()let img = $('#testImg')if (img.length === 1) {let pageX = event.pageXlet pageY = event.pageYimg.css({position: 'absolute',left: pageX - 20 + 'px',top: pageY - 20 + 'px'})}})
节点右键编辑
点击线操作
代码在不断完善中,有不错的建议和意见欢迎提出!