jsplumb中文教程地址: https://wdd.js.org/jsplumb-chinese-tutorial/#/
需求效果展示:
說明:在展示普通流程圖的基礎上,實現以下功能:在流程圖中展示當前所在節點,並體現出其流轉過程。上圖中當前節點爲分公司諮詢組,流轉過程爲:派單->省公司虛擬專家組->分公司諮詢組
安裝依賴包:npm i jsplumb
在main.js中將jsplumb掛在vue下便於頁面獲取
import jsPlumb from 'jsplumb'
Vue.prototype.$jsPlumb = jsPlumb.jsPlumb
主要代碼:
<div id="container">
<div class="col1">
<div id="processDefineDiv_node_2" name="cell">派單</div>
</div>
<div class="col2">
<div v-for="item in list2" :key="item.nodeId" :id="item.nodeId" name="cell">{{ item.name }}</div>
</div>
<div class="col3">
<div id="processDefineDiv_node_6" name="cell">完成</div>
</div>
</div>
// 樣式
#container{
position: relative;
width: 100%;
padding: 0 50px;
}
.col2,.col1{
float: left;
text-align: center;
}
.col3{
float: right;
text-align: center;
}
.col1{
width: 180px;
}
.col2{
width:200px;
margin: 0 200px;
}
.col3{
width: 180px;
}
#container>div>div{
line-height: 40px;
background: #496def;
margin: 50px 0;
}
節點中的id儘量設置爲可以從後臺返回的流轉數據中獲取的唯一的key值,可以較方便的控制當前所在節點的樣式,以下爲data中的相關數據
jsPlumb: null, // 緩存實例化的jsplumb對象
list2: [{ name: '省公司虛擬專家組', nodeId: 'processDefineDiv_node_3' }, { name: '分公司諮詢組', nodeId: 'processDefineDiv_node_5' }, { name: '縣諮詢組', nodeId: 'processDefineDiv_node_4' }], // 節點參數
connlist: [
{ sourceNodeId: 'processDefineDiv_node_2', targetNodeId: 'processDefineDiv_node_3' },
{ sourceNodeId: 'processDefineDiv_node_2', targetNodeId: 'processDefineDiv_node_5' },
// { sourceNodeId: 'processDefineDiv_node_2', targetNodeId: 'processDefineDiv_node_4' },
{ sourceNodeId: 'processDefineDiv_node_3', targetNodeId: 'processDefineDiv_node_5' },
{ sourceNodeId: 'processDefineDiv_node_5', targetNodeId: 'processDefineDiv_node_3' },
{ sourceNodeId: 'processDefineDiv_node_3', targetNodeId: 'processDefineDiv_node_6' },
{ sourceNodeId: 'processDefineDiv_node_5', targetNodeId: 'processDefineDiv_node_4' },
{ sourceNodeId: 'processDefineDiv_node_4', targetNodeId: 'processDefineDiv_node_5' },
{ sourceNodeId: 'processDefineDiv_node_5', targetNodeId: 'processDefineDiv_node_6' },
{ sourceNodeId: 'processDefineDiv_node_4', targetNodeId: 'processDefineDiv_node_6' }
], // 指定需要連接的兩節點
根據後臺獲取的節點流轉數據重置節點狀態
//後臺參考數據
this.oncedata = [
{proc_inst_task_code:'processDefineDiv_node_2',proc_inst_task_name:'派單'},
{proc_inst_task_code:'processDefineDiv_node_3',proc_inst_task_name:'省公司虛擬專家組'},
{proc_inst_task_code:'processDefineDiv_node_5',proc_inst_task_name:'分公司諮詢組'}
]
this.oncedata.forEach((item, index) => {
const ele = document.getElementById(item.proc_inst_task_code)
ele.style.backgroundColor = '#10af10' // 在流轉數據中的節點都改爲綠色背景
if (index === this.oncedata.length - 1) {
ele.style.backgroundColor = '#f11818' // 最後一個節點是最終狀態改爲紅色背景
}
})
在頁面創建時實例化流程圖
this.jsPlumb = this.$jsPlumb.getInstance({
Container: 'container', // 選擇器id
EndpointStyle: { radius: 0.11, fill: '#fff' }, // 端點樣式
// PaintStyle: { stroke: '#00ff00', strokeWidth: 2 }, // 繪畫樣式,默認8px線寬 #456
// HoverPaintStyle: { stroke: '#1E90FF' }, // 默認懸停樣式 默認爲null
// EndpointHoverStyle: { fill: '#F00', radius: 6 }, // 端點懸停樣式
// ConnectionOverlays: [ // 此處可以設置所有箭頭的樣式,因爲我們要改變連接線的樣式,故單獨配置
// ['Arrow', { // 設置參數可以參考中文文檔
// location: 1,
// length: 10,
// paintStyle: {
// stroke: '#496def',
// fill: '#496def'
// }
// }]
// ],
Connector: ['Straight', { gap: 1 }], // 要使用的默認連接器的類型:直線,折線,曲線等
DrapOptions: { cursor: 'crosshair', zIndex: 2000 }
},)
頁面掛載完成後,繪製連接線
const ins = this.jsPlumb
ins.getAllConnections()
ins.batch(() => {
this.initAll()
this.connectionAll()
})
this.switchContainer(true, true, false)
this.oncedata.forEach((item, index) => {
if (index < this.oncedata.length - 1) {
const connection = this.jsPlumb.connect({ // 對流程數據中對應的節點連接線重新繪製
source: item.proc_inst_task_code,
target: this.oncedata[++index].proc_inst_task_code,
overlays: [ ['Arrow', { width: 12,
length: 10,
location: 1,
paintStyle: {
stroke: '#10af10',
fill: '#10af10'
} }
] ]
})
connection.setPaintStyle({ stroke: '#10af10', strokeWidth: 2 })
}
})
methods中使用的主要方法
initAll () { // 初始化所有節點
this.init('processDefineDiv_node_2')
this.init('processDefineDiv_node_6')
const rl2 = this.list2
for (let i = 0; i < rl2.length; i++) {
this.init(rl2[i].nodeId)
}
},
// 初始化規則使其可以連線、拖拽
init (id) {
const ins = this.jsPlumb
const elem = document.getElementById(id)
ins.makeSource(elem, {
anchor: ['Perimeter', { anchorCount: 200, shape: 'Rectangle' }],
allowLoopback: false,
maxConnections: 1
})
ins.makeTarget(elem, {
anchor: ['Perimeter', { anchorCount: 200, shape: 'Rectangle' }],
allowLoopback: false,
maxConnections: 1
})
},
connectionAll () { 創建連接線
const ins = this.jsPlumb
ins.ready(() => { // 入口
for (let i = 0; i < this.connlist.length; i++) {
const conn = this.connlist[i]
const connection = ins.connect({
source: conn.sourceNodeId,
target: conn.targetNodeId,
overlays: [ ['Arrow', { width: 12,
length: 10,
location: 1,
paintStyle: {
stroke: '#496def',
fill: '#496def'
} }
] ]
})
connection.setPaintStyle({ stroke: '#496def', strokeWidth: 2 })
}
})
},
switchContainer (target, source, draggable) {
const elem = document.getElementsByName('cell')
const ins = this.jsPlumb
ins.setSourceEnabled(elem, source)
ins.setTargetEnabled(elem, target)
ins.setDraggable(elem, draggable) // 是否支持拖拽
}