import panzoom from "panzoom"; import { GenNonDuplicateID } from "@/common/until"; const methods = { init() { this.jsPlumb.ready(() => { // 导入默认配置 this.jsPlumb.importDefaults(this.jsplumbSetting); //完成连线前的校验 this.jsPlumb.bind("beforeDrop", evt => { let res = () => { } //此处可以添加是否创建连接的校验, 返回 false 则不添加; return res }) //断开连线后,维护本地数据 this.jsPlumb.bind("connectionDetached", evt => { this.deleLine(evt) }) this.loadEasyFlow(); // 会使整个jsPlumb立即重绘。 this.jsPlumb.setSuspendDrawing(false, true); // 连线创建成功后,维护本地数据 this.jsPlumb.bind("connection", evt => { this.addLine(evt) }); }); this.initPanZoom(); }, // 加载流程图 loadEasyFlow() { // 初始化节点 for (let i = 0; i < this.data.nodeList.length; i++) { let node = this.data.nodeList[i]; // 设置源点,可以拖出线连接其他节点 this.jsPlumb.makeSource(node.id, this.jsplumbSourceOptions); // // 设置目标点,其他源点拖出的线可以连接该节点 this.jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions); // this.jsPlumb.draggable(node.id); this.draggableNode(node.id) } // 初始化连线 this.jsPlumb.unbind("connection"); //取消连接事件 for (let i = 0; i < this.data.lineList.length; i++) { let line = this.data.lineList[i]; this.jsPlumb.connect( { source: line.from, target: line.to }, this.jsplumbConnectOptions ); } this.jsPlumb.bind("connection", evt => { let from = evt.source.id; let to = evt.target.id; this.data.lineList.push({ from: from, to: to, label: "连线名称", id: GenNonDuplicateID(8), Remark: "" }); }); //连线双击删除事件 this.jsPlumb.bind("dblclick",(conn, originalEvent) => { this.confirmDelLine(conn) }) }, // 拖动节点 draggableNode(nodeId) { this.jsPlumb.draggable(nodeId, { grid: this.commonGrid, drag: (params) => { this.alignForLine(nodeId, params.pos) }, start: () => { }, stop: (params) => { this.auxiliaryLine.isShowXLine = false this.auxiliaryLine.isShowYLine = false this.changeNodePosition(nodeId, params.pos) } }) }, //移动节点时,动态显示对齐线 alignForLine(nodeId, position) { let showXLine = false, showYLine = false this.data.nodeList.some(el => { if(el.id !== nodeId && el.left == position[0]+'px') { this.auxiliaryLinePos.x = position[0] + 60; showYLine = true } if(el.id !== nodeId && el.top == position[1]+'px') { this.auxiliaryLinePos.y = position[1] + 20; showXLine = true } }) this.auxiliaryLine.isShowYLine = showYLine this.auxiliaryLine.isShowXLine = showXLine }, // 检查节点位置 changeNodePosition(nodeId, pos) { this.data.nodeList.some(v => { if(nodeId == v.id) { v.left = pos[0] +'px' v.top = pos[1] + 'px' return true }else { return false } }) }, drag(ele, item) { this.currentItem = item; }, drop(event) { const containerRect = this.jsPlumb.getContainer().getBoundingClientRect(); const scale = this.getScale(); let left = (event.pageX - containerRect.left -60) / scale; let top = (event.pageY - containerRect.top -20) / scale; var temp = { ...this.currentItem, id: GenNonDuplicateID(8), top: (Math.round(top/20))*20 + "px", left: (Math.round(left/20))*20 + "px" }; this.addNode(temp); }, // 连线 addLine(line) { let from = line.source.id; let to = line.target.id; console.log('连线: ' + from + ' --> ' + to) this.data.lineList.push({ from: from, to: to, label: "连线名称", id: GenNonDuplicateID(8), Remark: "" }); }, // 确认删除连线 confirmDelLine(line) { if (confirm("确认删除该连线?")) { this.jsPlumb.deleteConnection(line) } else { // 用户点击了取消 alert("操作已取消!"); } // this.$Modal.confirm({ // title: '删除连线', // content: "

确认删除该连线?

", // onOk: () => { // this.jsPlumb.deleteConnection(line) // } // }) }, // 删除连线 deleLine(line) { this.data.lineList.forEach((item, index) => { if(item.from === line.sourceId && item.to === line.targetId) { console.log('删线: ' + item.from + ' -/- ' + item.to) this.data.lineList.splice(index, 1) } }) }, // dragover默认事件就是不触发drag事件,取消默认事件后,才会触发drag事件 allowDrop(event) { event.preventDefault(); }, getScale() { let scale1; if (this.jsPlumb.pan) { const { scale } = this.jsPlumb.pan.getTransform(); scale1 = scale; } else { const matrix = window.getComputedStyle(this.jsPlumb.getContainer()).transform; scale1 = matrix.split(", ")[3] * 1; } this.jsPlumb.setZoom(scale1); return scale1; }, // 添加新的节点 addNode(temp) { console.log('新增节点: ') console.log(temp) this.data.nodeList.push(temp); this.$nextTick(() => { this.jsPlumb.makeSource(temp.id, this.jsplumbSourceOptions); this.jsPlumb.makeTarget(temp.id, this.jsplumbTargetOptions); this.draggableNode(temp.id) }); }, initPanZoom() { const mainContainer = this.jsPlumb.getContainer(); const mainContainerWrap = mainContainer.parentNode; const pan = panzoom(mainContainer, { smoothScroll: false, bounds: true, // autocenter: true, zoomDoubleClickSpeed: 1, minZoom: 0.5, maxZoom: 2, //设置滚动缩放的组合键,默认不需要组合键 beforeWheel: (e) => { console.log(e) // let shouldIgnore = !e.ctrlKey // return shouldIgnore }, beforeMouseDown: function(e) { // allow mouse-down panning only if altKey is down. Otherwise - ignore var shouldIgnore = e.ctrlKey; return shouldIgnore; } }); this.jsPlumb.mainContainerWrap = mainContainerWrap; this.jsPlumb.pan = pan; // 缩放时设置jsPlumb的缩放比率 pan.on("zoom", e => { const { x, y, scale } = e.getTransform(); this.jsPlumb.setZoom(scale); //根据缩放比例,缩放对齐辅助线长度和位置 this.auxiliaryLinePos.width = (1/scale) * 100 + '%' this.auxiliaryLinePos.height = (1/scale) * 100 + '%' this.auxiliaryLinePos.offsetX = -(x/scale) this.auxiliaryLinePos.offsetY = -(y/scale) }); pan.on("panend", (e) => { const {x, y, scale} = e.getTransform(); this.auxiliaryLinePos.width = (1/scale) * 100 + '%' this.auxiliaryLinePos.height = (1/scale) * 100 + '%' this.auxiliaryLinePos.offsetX = -(x/scale) this.auxiliaryLinePos.offsetY = -(y/scale) }) // 平移时设置鼠标样式 mainContainerWrap.style.cursor = "grab"; mainContainerWrap.addEventListener("mousedown", function wrapMousedown() { this.style.cursor = "grabbing"; mainContainerWrap.addEventListener("mouseout", function wrapMouseout() { this.style.cursor = "grab"; }); }); mainContainerWrap.addEventListener("mouseup", function wrapMouseup() { this.style.cursor = "grab"; }); }, // 设置节点名称 setNodeName(nodeId, name) { console.log('设置节点 '+nodeId+' 名称为: ' + name) this.data.nodeList.some((v) => { if(v.id === nodeId) { v.nodeName = name return true }else { return false } }) }, //删除节点 deleteNode(node) { console.log('删除节点: ') console.log(node) this.data.nodeList.some((v,index) => { if(v.id === node.id) { this.data.nodeList.splice(index, 1) this.jsPlumb.remove(v.id) return true }else { return false } }) }, //更改连线状态 changeLineState(nodeId, val) { console.log(val) let lines = this.jsPlumb.getAllConnections() lines.forEach(line => { if(line.targetId === nodeId || line.sourceId === nodeId) { if(val) { line.canvas.classList.add('active') }else { line.canvas.classList.remove('active') } } }) }, //初始化节点位置 (以便对齐,居中) fixNodesPosition() { if(this.data.nodeList && this.$refs.flowWrap) { const nodeWidth = 120 const nodeHeight = 40 let wrapInfo = this.$refs.flowWrap.getBoundingClientRect() let maxLeft = 0, minLeft = wrapInfo.width, maxTop = 0, minTop = wrapInfo.height; let nodePoint = { left: 0, right: 0, top: 0, bottom: 0 } let fixTop = 0, fixLeft = 0; this.data.nodeList.forEach(el => { let top = Number(el.top.substring(0, el.top.length -2)) let left = Number(el.left.substring(0, el.left.length -2)) maxLeft = left > maxLeft ? left : maxLeft minLeft = left < minLeft ? left : minLeft maxTop = top > maxTop ? top : maxTop minTop = top < minTop ? top : minTop }) nodePoint.left = minLeft nodePoint.right = wrapInfo.width - maxLeft - nodeWidth nodePoint.top = minTop nodePoint.bottom = wrapInfo.height - maxTop - nodeHeight; fixTop = nodePoint.top !== nodePoint.bottom ? (nodePoint.bottom - nodePoint.top) / 2 : 0; fixLeft = nodePoint.left !== nodePoint.right ? (nodePoint.right - nodePoint.left) / 2 : 0; this.data.nodeList.map(el => { let top = Number(el.top.substring(0, el.top.length - 2)) + fixTop; let left = Number(el.left.substring(0, el.left.length - 2)) + fixLeft; el.top = (Math.round(top/20))* 20 + 'px' el.left = (Math.round(left/20))*20 + 'px' }) } }, } export default methods;