代码拉取完成,页面将自动刷新
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<script src="jsplumb2.8.4.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>拖拽流Demo</title>
<style>
#diagramContainer {
user-select: none;
padding: 20px;
width: 80%;
height: 600px;
border: 1px solid gray;
position: relative;
}
.item {
position: absolute;
height: 60px;
width: 150px;
border: 1px solid #66B366;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
background: #ddd;
}
.btn-ct{
display: flex;
justify-content: flex-start;
margin-bottom: 10px;
}
.btn{
border: 1px solid #ddd;
border-radius: 3px;
padding: 10px;
cursor: pointer;
user-select: none;
margin: 0 5px;
}
.aLabel {
background-color:white;
opacity:0.8;
padding:0.3em;
}
</style>
</head>
<body>
<div id="vue-ct">
<h3>
{{ message }}
</h3>
<div class="btn-ct">
<div class="btn" @click="addEl()">
添加节点
</div>
<div class="btn" @click="clearElCon()">
断开第一个元素的所有链接
</div>
<div class="btn" @click="removeEl()">
删除第一个元素
</div>
<div class="btn" @click="addConFromData()">
所有块和起点建立链接
</div>
<div class="btn" @click="reset()">
清空
</div>
</div>
<div id="diagramContainer">
<template v-for="(item,index) in elementsList">
<div :id="item.id" :style="item.style" class="item">
<template v-if="index === 0">
假装是起点
</template>
<template v-else>
流程
</template>
</div>
</template>
</div>
</div>
<script>
var app = new Vue({
el: '#vue-ct',
data: {
message: '拖拽流Demo:Vue + jsPlumb',
// jsPlumb实例
_jsPlumb:null,
// 基本设置
commonOption:{
// 拖拽设置
DragOptions: {
cursor: 'pointer',
zIndex: 2000,
containment: 'diagramContainer',
grid: [5, 5],
},
Connector: [ "Flowchart", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true } ],
// 元素连接点的样式
EndpointStyle: { fill: 'transparent',radius:0 },
// 连接线端点样式
// Endpoints : [ [ "Dot", { radius:7 } ], [ "Dot", { radius:7 } ] ],
// EndpointStyles : [{ fill: 'transparent',radius:0 }, { fill: 'transparent',radius:0 }],
// 连接线样式
PaintStyle: {
stroke: "rgba(122, 176, 44, 0.6)",
fill: "transparent",
radius: 5,
strokeWidth: 3
},
// 连接线hover样式
HoverPaintStyle: {
stroke: "red",
strokeWidth: 3,
},
// 添加连接线箭头和label
ConnectionOverlays: [
[ "Arrow", {
location: 1,
visible:true,
width:11,
length:11,
id:"ARROW",
events:{
click:function() { alert("你点击了箭头!")}
}
} ],
],
MaxConnections:-1,
// 设置容器
Container: "diagramContainer",
},
// 源元素设置
sourceEndpointOpt : {
isSource: true,
endpoint: "Dot",
connector: [ "Flowchart", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true } ],
paintStyle: {
stroke: "#7AB02C",
fill: "transparent",
radius: 7,
strokeWidth: 1
},
hoverPaintStyle: {
// fill: "#216477",
// stroke: "#216477",
stroke: "rgba(122, 176, 44, 0.6)",
fill: "rgba(122, 176, 44, 0.6)",
},
dragOptions: {},
overlays: [
[ "Label", {
location: [0.5, 1.5],
label: "Drag",
cssClass: "endpointSourceLabel",
visible:false
} ]
]
},
// 目标元素设置
targetEndpointOpt : {
isTarget: true,
endpoint: "Dot",
paintStyle: { fill: "rgba(122, 176, 44, 0.6)", radius: 7 },
hoverPaintStyle: {
// fill: "#216477",
// stroke: "#216477"
stroke: "rgba(122, 176, 44, 0.6)",
fill: "rgba(122, 176, 44, 0.6)",
},
dropOptions: { hoverClass: "hover", activeClass: "active" },
overlays: [
[ "Label", { location: [0.5, -0.5], label: "Drop", cssClass: "endpointTargetLabel", visible:false } ]
]
},
elementsList:[
{
id:'item_test1',
sourceAnchors: ['BottomCenter'],
targetAnchors: [],
style:{
top:'300px',
left: '400px'
}
},
]
},
methods:{
jsPlumbInit(){
let _this = this;
jsPlumb.ready(function () {
// 创建单独的实例
_this.createInstance();
// 添加元素
_this.elementsList.map(item => {
_this.jsPlumbAddItem(item);
});
// 添加事件
_this.listenEvent();
})
},
createInstance(){
let _this = this;
_this._jsPlumb = jsPlumb.getInstance(_this.commonOption);
},
jsPlumbAddItem(item){
let _this = this;
// 添加锚点
let {sourceAnchors,targetAnchors,id} = item;
sourceAnchors.map((sourceAnchor) => {
let sourceUUID = id + sourceAnchor;
_this._jsPlumb.addEndpoint(id, _this.sourceEndpointOpt, {
anchor: sourceAnchor,
uuid: sourceUUID
});
});
targetAnchors.map((targetAnchor) => {
let targetUUID = id + targetAnchor;
_this._jsPlumb.addEndpoint(id, _this.targetEndpointOpt, {
anchor: targetAnchor,
uuid: targetUUID
});
});
// 添加元素可拖动属性
_this._jsPlumb.draggable(item.id);
// 防止回环连接(好像没什么用)
// _this._jsPlumb.makeTarget(item.id, {
// allowLoopback:false
// });
},
listenEvent(){
let _this = this;
// 添加连接线点击事件
_this._jsPlumb.bind('click', function (conn, originalEvent) {
console.log(conn)
_this._jsPlumb.deleteConnection(conn);
});
// 连接前事件
_this._jsPlumb.bind('beforeDrop', function (info) {
console.log('连接前:',info);
return _this.whetherConnect(info.connection.sourceId,info.connection.targetId);
});
// 连接事件
_this._jsPlumb.bind('connection', function (info) {
console.log('已连接:',info);
return true;
});
// 连接Detached事件
_this._jsPlumb.bind('connectionDetached', function (info) {
console.log('连接Detached:',info);
return true
});
// 连接Moved事件
_this._jsPlumb.bind('connectionMoved', function (info) {
console.log('连接Moved:',info);
return true
})
},
// 计算是否能够连接
whetherConnect(sourceId,targetId){
let _this = this;
let canConnect = true;
// 判断重复连接
let fmtArr = _this._jsPlumb.getConnections().map(item => {
if(item.sourceId === sourceId && item.targetId === targetId){
canConnect = false;
console.log('该连接为重复连接')
}
return {
sourceId:item.sourceId,
targetId:item.targetId,
}
});
if(!canConnect){
return canConnect
}
// 有向无环图
let hasMatchA = false;
function DAG(arr,fromA,toB) {
arr.map((item,index) => {
if(item.sourceId === toB){
if(item.targetId === fromA){
hasMatchA = true;
}else{
let _arr = [...arr];
_arr.splice(index,1);
DAG(_arr,fromA,item.targetId)
}
}
})
}
DAG(fmtArr,sourceId,targetId);
if(hasMatchA){
canConnect = false;
alert('形成回环')
}
return canConnect
},
addEl(){
let top = `${100 + Math.random() * 500}px`;
let left = `${100 + Math.random() * 500}px`;
let id = `item_test${parseInt(Math.random() * 100)}`
let newEl = {
id: id,
sourceAnchors: ['BottomCenter'],
targetAnchors: ['TopCenter'],
style:{
top: top,
left: left
}
};
this.elementsList.push(newEl);
this.$nextTick(() => {
this.jsPlumbAddItem(newEl);
})
},
clearElCon(){
let _this = this;
// 删除与“item_test1”的所有连接
_this._jsPlumb.deleteConnectionsForElement('item_test1')
},
removeEl(){
let _this = this;
_this._jsPlumb.remove('item_test1')
},
/*
* 参考文档:https://jsplumbtoolkit.com/community/doc/connections.html#sourcefilter
* */
addConFromData(){
let _this = this;
this.elementsList.map( (item,index) => {
if(index !== 0 && _this.whetherConnect(_this.elementsList[0].id,item.id)){
_this._jsPlumb.connect({
source:_this.elementsList[0].id,
target:item.id,
anchors:["BottomCenter", "TopCenter" ],
},_this.commonOption);
}
})
},
reset(){
let _this = this;
_this._jsPlumb.deleteEveryConnection();
}
},
mounted(){
this.jsPlumbInit();
}
})
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。