333 lines
10 KiB
JavaScript
333 lines
10 KiB
JavaScript
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: "<p>确认删除该连线?</p>",
|
||
// 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;
|