Jsplumb 配合 Vue用法实践
效果图目前已完成功能:加载左侧列表菜单加载右侧表单数据,并根据连接类型进行对应的连线用户操作功能, 包括连线;连线条件判断;修改连线属性;左侧菜单拖动模型到右侧区域;鼠标滚轮缩放右侧区域,鼠标拖拽移动背景等保存功能,每次连线、新建模型请求接口保存属性,还有保存按钮可以保存当前全部数据计划新功能:计划在右下角增加缩略图,可以点击缩略图的位置,移动大背景图功能代码:左侧菜单拖拽模型到右侧,需要绑定两个
效果图
目前已完成功能:
- 加载左侧列表菜单
- 加载右侧表单数据,并根据连接类型进行对应的连线
- 用户操作功能, 包括连线;连线条件判断;修改连线属性;左侧菜单拖动模型到右侧区域;鼠标滚轮缩放右侧区域,鼠标拖拽移动背景等
- 保存功能,每次连线、新建模型请求接口保存属性,还有保存按钮可以保存当前全部数据
计划新功能:
计划在右下角增加缩略图,可以点击缩略图的位置,移动大背景图
功能代码:
右侧画布内的模型拖拽:
vm.jsplumb.draggable(document.querySelectorAll('.model'), {
// 设置拖拽区域不超过父级
containment: 'parent',
stop: function (e){
// 拖拽后改变位置,修改本地数据
}
});
左侧菜单拖拽模型到右侧,需要绑定两个事件,一个拖拽事件,一个在右侧区域放置事件
1. 左侧菜单拖拽事件
vm.jsplumb.draggable(document.querySelectorAll('.left-sub-title'), {
helper: 'clone',
scope: 'ss',
drag: function (e){
vm.isDragging = true;
// 在鼠标拖拽处创建一个元素, 设置元素和拖拽模型拥有相同名称,并使元素随鼠标拖拽移动
vm.showName = e.el.textContent;
vm.$refs.controlNode.style.left = e.el.style.left;
vm.$refs.controlNode.style.top = e.el.style.top;
},
stop: function () {
vm.isDragging = false;
}
})
2. 右侧放置事件
// 右侧区域放置事件,设置相同的scope
vm.jsplumb.droppable('points', {
scope: 'ss',
drop: function (event){
// 计算放置位置
let leftP = ((event.e.x - event.drag.el.offsetWidth) / event.drop.el.offsetWidth).toFixed(2) * 100;
let topP = (event.e.y / event.drop.el.offsetHeight).toFixed(2) * 100;
//.... 请求接口数据
vm.isDragging = false;
vm.showName = '';
vm.$nextTick(() => {
vm.addNew();
});
}
})
addNew(){
// 为新的模型添加事件
let lastIndex = Object.keys(vm.data.formMap).length - 1
let lastNode = vm.data.formMap[Object.keys(vm.data.formMap)[lastIndex]];
vm.jsplumb.draggable(document.querySelectorAll('.point')[lastIndex], {
containment: 'points',
// 拖拽后改变位置,把x, y坐标存入数据(我是用了百分比)
stop: function (e){
vm.data.formMap[e.el.id].x = (e.pos[0] / e.el.parentNode.offsetWidth).toFixed(2) * 100;
vm.data.formMap[e.el.id].y = (e.pos[1] / e.el.parentNode.offsetHeight).toFixed(2) * 100;
}
});
// 每行添加anchor连线点
vm.jsplumb.batch(() => {
for (const m in lastNode.fieldMap){
vm.jsplumb.makeSource(Object.keys(vm.data.formMap)[lastIndex] + '-' + m, {
anchor: ["Continuous", { faces: ["left", "right"] }],
endpoint: 'Dot',
});
vm.jsplumb.makeTarget(Object.keys(vm.data.formMap)[lastIndex] + '-' + m, {
anchor: ["Continuous", { faces: ["left", "right"] }],
allowLoopback: false
});
}
})
}
给每行添加anchor锚点时,要给每个描点设置id,这样后面的连线才能正确连接。
然后是加载右侧数据,因为用的Vue,所以不用在下面疯狂创建元素了,直接v-for写在template里,只需要后面绑定事件即可,绑定事件代码和上面addNew是一致的,只不过后面需要添加连线:
vm.jsplumb.connect({
source: targetLines[line].formId + '-' + targetLines[line].fieldId,
target: targetLines[line].targetFormId + '-' + targetLines[line].targetFieldId,
paintStyle: { strokeWidth: 1, stroke: targetLines[line].lineType === 1 ? '#409EFF' : '#67C23A' },
hoverPaintStyle: { stroke: targetLines[line].lineType === 1 ? '#66b1ff' : '#85ce61', strokeWidth: 3 },
overlays: [
[
"Arrow",
{
location: 1,
visible: true,
width: 11,
length: 11,
id: "ARROW",
}
], [
"Label",
{
location: 0.5,
label: targetLines[line].lineType === 1 ? '关联' : '推送',
visible: true,
id: "label",
cssClass: "aLabel",
}
]]
});
循环没放出来,jsplumb.connect 就是连线操作,soure填写起点的锚点id,target为终点锚点id,overlays可以设置连线属性,包括箭头位置样式和文字说明。
连线事件(beforeDrop 和 connection):
vm.jsplumb.bind('beforeDrop', function (conn){
// 根据conn的sourceId和targetId判断是否满足连线条件
// 代码.....
// 最后return 为 false 则不会连线
});
vm.jsplumb.bind("connection", function (connInfo, originalEvent){
// 调用接口,保存连线
});
点击连线可以修改连线样式:
// 点击连线事件
vm.jsplumb.bind('click', function (conn, originalEvent){
// 点击连线弹出窗口进行修改操作
vm.editTable(conn);
});
// 弹出修改弹窗
editTable(conn){
let vm = this;
vm.editVisible = true;
// 连线属性设置
vm.currentConn = conn;
},
// 保存操作
tableChange(){
// 保存修改后连线
this.editVisible = false;
// 修改连线文字说明
this.currentConn.getOverlay("label").setLabel(this.tableForm.lineType === 1 ? '关联' : '推送');
// 修改连线颜色
this.currentConn.setPaintStyle({ strokeWidth: 1, stroke: this.tableForm.lineType === 2 ? "#67C23A" : '#409EFF' });
this.currentConn.setHoverPaintStyle({
strokeWidth: 3,
stroke: this.tableForm.lineType === 2 ? "#85ce61" : '#66b1ff'
});
// 更新本地数据。。。
},
鼠标滚轮缩放以及可拖拽画布:
mounted(){
jsPlumb.ready(() => {
// 初始化模型,进行添加事件、增加锚点、初始化连线
});
// 鼠标滚路事件
document.onmousewheel = (e) => {
if (e.target.id === 'points-parent' || e.target.id === 'points'){
this.setZoom(e);
}
}
},
computed: {
calZoom(e){
if (e > 0){
this.zoom += 0.1
}else if (e < 0){
this.zoom -= 0.1
}
}
this.zoom 是html元素画布的动态 scale 属性:
"-webkit-transform": `scale(${this.zoom)})`,
需要注意的问题:
如果初始化jsplumb实例的时候设置了ConnectionOverlays的label文字,在进行connect连线操作室如果想要动态改变文字,不能在connect方法里设置overlay的label属性,需要在方法外(也就是连线后设置):
this.jsplumb.connect({...}).getOverlay('label的id').setLabel('新的label文字')
更多推荐
所有评论(0)