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',