使⽤jsPlumb插件实现动态连线功能
这周去看了两天的⽻⽑球亚锦赛,⼯作有提前晚上加班做⼀些,但是技术⽂章却拉下了。
这段时间⼀直在寻可以实现前端元素动态连线的功能,了好⼏个库,考虑过⽤d3或者原⽣svg和canvas来实现,最后和同项⽬的同事商量后决定使⽤jsPlumb插件库来做。
jsPlumb是⼀个强⼤的JavaScript连线库,它可以将html中的元素⽤箭头、曲线、直线等连接起来,适⽤于开发Web上的图表、建模⼯具等,其实jsPlumb可能主要是⽤来做流程
图的,它在实现这⽅⾯的功能上⾮常强⼤,我在项⽬中只使⽤了它少部分功能,来实现项⽬中连线的效果。
连线效果
initJSPlumb = () => {
this.jsp = Instance({
//锚点位置;对任何没有声明描点的Endpoint设置锚点,⽤于source及target节点
Anchor: ["Right", "Left"],
Anchors: ["Right", "Left"],  //连线的source和target Anchor
ConnectionsDetachable: false, //连线是否可⽤⿏标分离
ConnectionOverlays: [  //连线的叠加组件,如箭头、标签
["Arrow", {  //箭头参数设置
location: 1,
visible: true,
width: 11,
length: 11,
id: "ARROW",
代码运行js特效events: {
click: function () {
}
}
}],
["Label", {  //标签参数设置
location: 0.1,
id: "label",
cssClass: "aLabel", //hover时label的样式名
events: {
tap: function () {
}
},
visible: true
}]
],
Connector: "Bezier", //连线的类型,流程图(Flowchart)、贝塞尔曲线等
//⽗级元素id;假如页⾯元素所在上层不同,最外层⽗级⼀定要设置
Container: "module",
//如果请求不存在的Anchor、Endpoint或Connector,是否抛异常
DoNotThrowErrors: false,
//通过jsPlumb.draggable拖拽元素时的默认参数设置
DragOptions: {cursor: 'pointer', zIndex: 2000},
DropOptions: {}, //target Endpoint放置时的默认参数设置
Endpoint: "Dot", //端点(锚点)的样式声明
//⽤t创建连接时,source端点和target端点的样式设置
Endpoints: [null, null],
EndpointOverlays: [], //端点的叠加物
//端点的默认样式
EndpointStyle: {fill: 'transparent', stroke: '#1565C0', radius: 4,
strokeWidth: 1},
EndpointStyles: [null, null], //连线的source和target端点的样式
//端点hover时的样式
EndpointHoverStyle: {fill: '#1565C0', stroke: '#1565C0', radius: 4,
strokeWidth: 1},
//连线的source和target端点hover时的样式
EndpointHoverStyles: [null, null],
//连线hover时的样式
HoverPaintStyle: {stroke: '#1565C0', strokeWidth: 3},
LabelStyle: {color: "black"}, //标签的默认样式,⽤css写法。
LogEnabled: false, //是否开启jsPlumb内部⽇志
Overlays: [], //连线和端点的叠加物
MaxConnections: 10, //端点⽀持的最⼤连接数
//连线样式
PaintStyle: {stroke: '#1565C0', strokeWidth: 1, joinstyle: 'round'},
ReattachConnections: true, //是否重新连接使⽤⿏标分离的线?
RenderMode: "svg", //默认渲染模式
Scope: "jsPlumb_DefaultScope", //范围,具有相同scope的点才可连接
reattach: true,
})
this.jsp.bind('beforeDrop', this.jspBeforeDrop)
}
以上是初始化jsPlumb对象的函数。
接下来获取数据,加载页⾯的系统和编制模块。
fetchDataForLeft(data) {
var jsonString_left = '[{"module_name":"crm系统","module_id":"A","nodes":[{"id":"A-1","text":"开始","pos
ition":"left"},{"id":"A-2","text":"过程","position":"left"},{"id":"A-3","text":"过程ing","position":"left"}]},{"module_name":"财务系统","module_id":    var jsonString_right = '[{"module_name":"年度预算编制","module_id":"C","nodes":[{"id":"C-1","text":"结束","position":"right"}]},{"module_name":"营收编制","module_id":"D","nodes":[{"id":"D-1","text":"结束","position":"right"}]}]';
// var nodeData_left = JSON.parse(jsonString_left);
//[{"entity":null,"id":"934D62BD0F8249B09F29EC9FA051E390","code":"1","name":"CRM","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{
var nodeData_left = data;
this.setState({
nodes_left: nodeData_left,
})
//绘制左边点
nodeData_left.map((node, index) => {
this.setState({datas: node, nodes: node.fromModelList}, () => {
this.fs.nodes_left[index], 'left');
// this.initEdges(nodeData.edges);
});
})
//绘制右边点
// nodeData_right.map((node, index) => {
//    this.setState({data_right: node, node_right: ModelList}, () => {
//        this.fs.nodes_right[index], 'right');
//        // this.initEdges(nodeData.edges);
//    });
/
/ })
}
fetchDataForRight(data){
var jsonString_left = '[{"module_name":"crm系统","module_id":"A","nodes":[{"id":"A-1","text":"开始","position":"left"},{"id":"A-2","text":"过程","position":"left"},{"id":"A-3","text":"过程ing","position":"left"}]},{"module_name":"财务系统","module_id":    var jsonString_right = '[{"module_name":"年度预算编制","module_id":"C","nodes":[{"id":"C-1","text":"结束","position":"right"}]},{"module_name":"营收编制","module_id":"D","nodes":[{"id":"D-1","text":"结束","position":"right"}]}]';
// var nodeData_left = JSON.parse(jsonString_left);
//[{"entity":null,"id":"934D62BD0F8249B09F29EC9FA051E390","code":"1","name":"CRM","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{
var nodeData_right = data;
this.setState({
nodes_right: nodeData_right
})
//绘制右边点
nodeData_right.map((node, index) => {
this.setState({data_right: node, node_right: ModelList}, () => {
this.fs.nodes_right[index], 'right');
// this.initEdges(nodeData.edges);
});
})
}
初始化连接锚点
initNodes = (node, position) => {
this.jsp.setSuspendDrawing(true);
if (position === "left") {
DynamicAnchors.map(anchor => this.rjsp.addEndpoint(node, anEndpoint, {anchor: "Right"}));
} else {
DynamicAnchors_Right.map(anchor => this.rjsp.addEndpoint(node, anEndpoint, {anchor: "Left"}));    }
this.rjsp.setSuspendDrawing(false, true);
}
//⾃动连线
initEdges = (edges) => {
this.rjsp.setSuspendDrawing(true);
edges.map(edge => {
t(edge, Common);
})
this.jsp.setSuspendDrawing(false, true);
}