首先:在vue项目中安装jsplumb
执行 npm install jsplumb --save
绘制拓扑图
1、创建jsplumb实例
import {jsPlumb} from 'jsplumb'
export default {
data() {
return {
jsplumbInstance: null, // jsplumb实例
}
},
methods: {
initData() {
// 创建jsplumb实例
this.jsplumbInstance = jsPlumb.getInstance();
}
}
}
2、jsplumb设置拓扑节点可以进行拖动。eleId表示当前拖动节点的id。默认情况下,节点可以拖动到画布区域外面,设置containment: 'parent',表示节点只能在自己的父元素内进行拖动,在我代码里,父元素代表画布区域。
makeTopoNodeDrag(eleId) {
this.jsplumbInstance.draggable(eleId, {containment: 'parent'});
}
3、jsplumb给每一个节点添加端点。addEndpoint方法可以用来添加端点。
addEndPoints(eleId) {
let style = {
endpoint: 'Dot',
// 将isSource和isTarget设置为true,可以在拖动时自动创建连接
isSource: true,
isTarget: true,
connector: ['Flowchart', { cornerRadius: 10 }],
// 默认情况下,maxConnections为1,表示一个端点只能有一条连线。设置为-1,不限制连线数量
maxConnections: -1,
// 端点样式
paintStyle: {
fill: 'rgba(54,54,54,0)',
},
// 鼠标悬浮端点样式
hoverPaintStyle: {
fill: 'rgba(64,54,54,0.5)',
},
// 拖拽连线样式
connectorStyle: {
stroke: 'rgba(54, 61, 63, 0.5)',
strokeWidth: 3,
},
connectorHoverStyle: {
stroke: 'rgba(54, 61, 63, 0.5)',
strokeWidth: 5,
},
// 设置箭头
connectorOverlays: [['Arrow', { width: 10, location: 1, id: 'arrow' }]],
}
this.jsplumbInstance.addEndpoint(
{eleId, {anchors: 'TopCenter'}, style};
{eleId, {anchors: 'BottomCenter'}, style};
{eleId, {anchors: 'LeftMiddle'}, style};
{eleId, {anchors: 'RightMiddle'}, style};
)
}
4、基于上述步骤,节点元素已经放置在画布上,并且为节点添加了上下左右4个锚点,在锚点上进行拖拽连线:
在连线之前,有时会根据一些特定条件判断是否进行连接,不符合条件时,不能进行连接,可以使用beforeDrop事件,具体参数info,可以查看https://www.jianshu.com/p/c2c4f7fdffa1(别人的文章)
// 监听连线事件
monitorLineConnection() {
this.jsPlumbInstance.bind('beforeDrop', info => {
// 禁止在同一端点上连接
if(info.sourceId === info.targetId) {
return false; // return false连接不会建立,必须为false
}
// 可以在连接前再添加判断条件,例如一个节点上的同一个端点只能连接一次等等。。省略代码
return true; // 连接自动建立
})
}
5、第3步给每一个节点添加了端点,可以使用removeAllEndpoints方法删除节点上的端点。
// eleId表示当前节点的id
this.jsplumbInstance.removeAllEndpoints(eleId);
6、删除连线,deleteConnection方法删除连线
// 添加右键事件,当右键点击在连线上时,info就是当前的连线信息,deleteConnection方法可以删除当前连线
this.jsPlumbInstance.bind('contextmenu', info => {
let lineInfo = info;
this.jsPlumbInstance.deleteConnection(lineInfo);
})
以上步骤基本上就可以实现简单的拖拽连线功能。
通常情况下,可能需要根据现有的数据直接使用jsplumb将拓扑图绘制出来:this.jsPlumbInstance.connect()
export default {
data() {
return {
topoData: [], // 拓扑数据
}
},
methods: {
initData() {
this.jsPlumbInstance.ready(() => {
this.topoData.forEach(item => {
item.target.forEach(target => {
this.jsPlumbInstance.connect(
{
source: item.id,
target: target.id,
anchors: target.anchors,
}, style
)
})
})
})
},
},
mounted() {
this.initData();
}
}
代码中的style表示连线的样式:
let style = {
connector: ['Flowchart', { cornerRadius: 10 }],
// 一般情况下再次拖动连线时,连接会断开,设置 detachable: false 可以阻止这种行为
detachable: false,
// 线段样式
paintStyle: {
stroke: '#000',
strokeWidth: 3,
},
// 鼠标经过线段样式
hoverPaintStyle: {
stroke: '#000',
strokeWidth: 5,
},
endpointStyle: { fill: 'none' }, // 端点样式
// 设置箭头,Label等
overlays: [
[
'Arrow',
{
width: 10,
location: 1,
id: 'arrow',
},
],
],
}
拓扑数据的格式是:
{
"data": [
{
"name": "第一个元素",
"id": "1",
"top": "112", // top,left表示元素在画布上位置
"left": "298",
"target": [ // target数组表示当前节点所连接的节点及连接锚点位置信息
{
"id": "2",
"anchors": [
"BottomCenter",
"TopCenter"
]
}
]
},
{
"name": "第二个元素",
"id": "2",
"top": "259",
"left": "298",
"target": [
{
"id": "3",
"anchors": [
"LeftMiddle",
"TopCenter"
]
}
]
},
{
"name": "第三个元素",
"id": "3",
"top": "442",
"left": "298",
"target": [
{
"id": "4",
"anchors": [
"BottomCenter",
"TopCenter"
]
}
]
}
]
}