jsplumb 有2個版本一個Toolkit Edition(付費版),另一個就是Community Edition(社區版本)。Toolkit Edition版本功能集成的比較豐富,社區版本的就差好多,不少功能都沒有,須要咱們本身去添加,固然了本身添加多多少少有些麻煩,並且也不完善。可是咱們仍是用Community Edition(社區版本),畢竟不收費,沒辦法,下邊所說的版本默認都是以社區版。javascript
最近公司項目有用到這個流程圖,因此也就看到了這個框架,這個框架是英文版本的,地址:https://jsplumbtoolkit.com/community/doc/home.html(能夠用瀏覽器翻譯了看)。他的缺陷就是文檔不全,api感受也有點亂,實例交代的也不清楚,github地址是:https://github.com/jsplumb/jsplumb (裏面有demo,本身能夠下載運行,多動手試試)。若是隻是簡單的畫個圖,這個框架是沒有什麼問題的,demo裏也有,可是若是要實現高級的動能呢鞥,仍是得多多嘗試。此文也是記錄一下我本身用到的一些功能,不少我還沒用到,用到了在慢慢補充。css
上圖也就是我此次用到的jsplumb實現的功能,鏈接線可以拖拽生成,也能夠刪除,編輯label。html
{
"nodes": [{ //節點集合 "icon": "el-icon-loading", "id": "start", "nodeStyle": { "top": 100, "left": 200 }, "text": "開始", "type": "circle" }, { "icon": "el-icon-upload", "id": "end", "nodeStyle": { "top": 300, "left": 400 }, "text": "結束", "type": "circle" }] , "connections": [{ //鏈接線集合 "sourceId": "start", "targetId": "end", "label":"編輯" }] }
jsplumb實例裏面的數據結構就是這樣的,這裏咱們沿用他的數據結構,你也能夠本身定義本身想的數據結構,可是對比起來這個結構是最清晰也最方便的。vue
jsplumb在DOM渲染完畢以後纔會執行,因此須要爲jsplumb的執行代碼綁定一個ready事件:java
jsPlumb.ready(function() { // your jsPlumb related init code goes here });
jsplumb默認是註冊在瀏覽器窗口的,將整個頁面提供給咱們做爲一個實例,但咱們也能夠使用getInstance方法創建頁面中一個獨立的實例:node
var _instance = jsPlumb.getInstance();
let instance = jsPlumb.getInstance({ PaintStyle:{ strokeWidth:2, stroke:"#567567", } }) //拖拽功能 var els = document.querySelectorAll(".box");//.box是容許拖拽的元素class類名 instance.draggable(els,{ containment:true, filter: ".ep",//除去不能拖拽的,這裏是個class類名 }); //不容許拆卸鏈接,不設置的話默認是能夠的 instance.importDefaults({ ConnectionsDetachable:false });
// 監聽拖動connection 事件,判斷是否有重複連接 instance.bind("beforeDrop", function(info) { // info.connection.getOverlay("label").setLabel(info.connection.id); // 判斷是否已有該鏈接 let isSame = true; //下邊的forEach循環就是處理數據結構裏的connections不能本身跟本身連線。固然你也能夠處理其餘 _this.chartData.connections.forEach(item => { if ((item.targetId === info.targetId && item.sourceId === info.sourceId) || (item.targetId === info.sourceId && item.sourceId === info.targetId)) { isSame = false; } }); if (isSame) { //容許連線後處理的狀況 } else { alert("不容許重複鏈接!"); } return isSame;//這裏返回了ture就會自定進行連線。 });
下邊代碼就是實現上圖的,須要指出的是運用了vue,可是裏面摻雜了jquery,和jquery-ui,其實不想用這2個的,可是項目緊,以前項目也用到了,因此就延續了。還有就是上面代碼是我本身的測試代碼,寫的可能有些雜亂,就是測試一個一個功能而寫,寫的有點亂。jquery
還有一個想說的就是以前想實現,縮放,引入了panzoom.js,流程圖也實現了滾動鼠標放大放小,可是有個問題就是滾動鼠標放大放小後若是拖動單個元素或者連線,你就會發現鼠標點對不齊了,這點尚未解決,若是有好的方案,能夠告知我下。Toolkit Edition(付費版)的這些功能都有,就不會出現這樣的問題。ios
<template> <div id="test6" style="height:100%;position:relative"> <section id="focal" style="position:relative;overflow:hidden;width:610px;height:610px;background:#fff;border:1px solid red"> <div class="parent" id="parent" style="height:100%;"> <div class="panzoom" id="panzoom" style="border:1px solid blue;width:6000px;height:6000px; transform:translate(-50%, -50%);position:absolute;"> <div class="box" :id="item.id" :style="{'top':item.nodeStyle.top+'px','left':item.nodeStyle.left+'px'}" v-for="item in chartData.nodes" :key="item.id"> <i :class="item.icon" class="oldIcon" :title="item.text"></i> <i class="el-icon-circle-close" style="display:none" :title="item.text" :id="item.id"></i> <div class="ep"></div> </div> </div> </div> </section> <div class="source"> <ul> <li v-for="(item,index) in list" :id="item.id" :key="index" class="sourceLi" :disabled="true" :data-icon="item.icon" :data-text="item.text" :data-type="item.type">{{item.text}}</li> </ul> </div> <el-dialog title="修改label名稱" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"> <el-input v-model="labelName" placeholder="請輸入"></el-input> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="changeNote">確 定</el-button> </span> </el-dialog> </div> </template> <script> import ChartNode from "@/components/ChartNode"; export default { name: "test6", data() { return { dialogVisible:false, labelName:"", curSourceId:'', curTargetId:'', addLabelText:'',//拖拽後生成的連線label文字 jsp:null, myscale:1, curScreen:[],//當前屏幕寬高 chartData: { nodes: [], connections: [],//{ "targetId": "box2", "sourceId": "box1" } props: {}, screen:[610,610]//提交屏幕寬高 }, list: [ { icon: "el-icon-goods", text: "伴隨車牌", type: "circle", id:'li1' }, { icon: "el-icon-bell", text: "常住人口篩選", type: "diamond", id:"li2" }, { icon: "el-icon-date", text: "伴隨imsi", type: "circle", id:"li3" } ] }; }, mounted() { let _this = this jsPlumb.ready(function() { var $section = $('#focal'); var $panzoom = $section.find('.panzoom').panzoom({ minScale: 0.3, maxScale:2, eventNamespace: ".panzoom", $zoomRange: $(".jtk-endpoint"), $set: $section.find('.jtk-overlay'), eventsListenerElement: document.querySelector('.box') }); $(document).on('mouseover','.box,.jtk-draggable,.jtk-overlay,.ep',function(){ $('.panzoom').panzoom("disable"); }) $(document).on('mouseleave',