vue+jsplumb实现工作流程图的方法
vue+jsplumb实现工作流程图的方法
这篇文章主要介绍“vue+jsplumb实现工作流程图的方法”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue+jsplumb实现工作流程图的方法”文章能帮助大家解决问题。
先写了一个demo,大概样子如下:
官网文档Home | jsPlumb Toolkit Documentation
先安装插件
npminstalljsplumb--save
安装panzoom,主要用于鼠标滚轮缩放流程图
npminstallpanzoom--save
在需要的页面引入插件
importpanzoomfrom'panzoom'import{jsPlumb}from'jsplumb'
接下来先写布局
父组件
<template><divclass="workflow"><divclass="flow_region"><divid="flowWrap"ref="flowWrap"class="flow-wrap"@drop="drop($event)"@dragover="allowDrop($event)"><divid="flow"><flowNodev-for="itemindata.nodeList":id="item.id":key="item.id":node="item"@setNodeName="setNodeName"@changeLineState="changeLineState"/></div></div></div></div></template>
flowNode是子组件
<template><divref="node"class="node-item":class="{isStart:node.type==='start',isEnd:node.type==='end','common-circle-node':node.type==='start'||node.type==='end'||node.type==='event','common-rectangle-node':node.type==='common'||node.type==='freedom'||node.type==='child-flow','common-diamond-node':node.type==='gateway','common-x-lane-node':node.type==='x-lane','common-y-lane-node':node.type==='y-lane'}":style="{top:node.y+'px',left:node.x+'px'}"@click="setNotActive"@mouseenter="showAnchor"@mouseleave="hideAnchor"><divclass="nodeName">{{node.nodeName}}</div></div></template>
样式主要是子组件的,父组件样式随意就行
<stylelang="less"scoped>@labelColor:#409eff;@nodeSize:20px;@viewSize:10px;.node-item{position:absolute;display:flex;height:40px;width:120px;justify-content:center;align-items:center;border:1pxsolid#b7b6b6;border-radius:4px;cursor:move;box-sizing:content-box;font-size:12px;z-index:9995;&:hover{z-index:9998;.delete-btn{display:block;}}.log-wrap{width:40px;height:40px;border-right:1pxsolid#b7b6b6;}.nodeName{flex-grow:1;width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center;}.node-anchor{display:flex;position:absolute;width:@nodeSize;height:@nodeSize;align-items:center;justify-content:center;border-radius:10px;cursor:crosshair;z-index:9999;background:-webkit-radial-gradient(sandybrown10%,white30%,#9a54ff60%);}.anchor-top{top:calc((@nodeSize/2)*-1);left:50%;margin-left:calc((@nodeSize/2)*-1);}.anchor-right{top:50%;right:calc((@nodeSize/2)*-1);margin-top:calc((@nodeSize/2)*-1);}.anchor-bottom{bottom:calc((@nodeSize/2)*-1);left:50%;margin-left:calc((@nodeSize/2)*-1);}.anchor-left{top:50%;left:calc((@nodeSize/2)*-1);margin-top:calc((@nodeSize/2)*-1);}}.active{border:1pxdashed@labelColor;box-shadow:0px5px9px0pxrgba(0,0,0,0.5);}.common-circle-node{border-radius:50%;height:60px;width:60px;}</style>
页面样式写完,接下来写插件配置
jsPlumb.ready() 是一个钩子函数,它会在 jsPlumb 准备完毕时执行。
连接线的建立是通过 jsPlumb.connect() 方法实现的。该方法接受一个对象作为配置项。其中包含了与上述概念一一对应的配置项,以及一些额外的样式。
source: 源对象,可以是对象的 id 属性、Element 对象或者 Endpoint 对象。
target: 目标对象,可以是对象的 id 属性、Element 对象或者 Endpoint 对象。
anchor: 是一个数组,数组中每一项定义一个锚点。
初始化方法
init(){this.jsPlumb.ready(()=>{//导入默认配置this.jsPlumb.importDefaults(this.jsplumbSetting)//完成连线前的校验this.jsPlumb.bind('beforeDrop',evt=>{constres=()=>{}//此处可以添加是否创建连接的校验,返回false则不添加;returnres})this.loadEasyFlow()//会使整个jsPlumb立即重绘。this.jsPlumb.setSuspendDrawing(false,true)})this.initPanZoom()},//加载流程图loadEasyFlow(){//初始化节点for(leti=0;i<this.data.nodeList.length;i++){constnode=this.data.nodeList[i]//设置源点,可以拖出线连接其他节点this.jsPlumb.makeSource(node.id,this.jsplumbSourceOptions)////设置目标点,其他源点拖出的线可以连接该节点this.jsPlumb.makeTarget(node.id,this.jsplumbTargetOptions)//this.jsPlumb.draggable(node.id);this.draggableNode(node.id)}//初始化连线this.jsPlumb.unbind('connection')//取消连接事件console.log(this.data.lineList)for(leti=0;i<this.data.lineList.length;i++){constline=this.data.lineList[i]constconn=this.jsPlumb.connect({source:line.sourceId,target:line.targetId,paintStyle:{stroke:line.cls.linkColor,strokeWidth:2//strokeWidth:line.cls.linkThickness}},this.jsplumbConnectOptions)conn.setLabel({label:line.label,cssClass:`linkLabel${line.id}`})}},
this.data 是需要渲染的数据,放在文章末尾,具体数据按照接口实际返回的来写
this.jsplumbSourceOptions 是jsplumb配置信息,新建一个文件编写,具体如下:
exportconstjsplumbSetting={grid:[10,10],//动态锚点、位置自适应anchor:['TopCenter','RightMiddle','BottomCenter','LeftMiddle'],Container:'flow',//连线的样式StateMachine、Flowchart,有四种默认类型:Bezier(贝塞尔曲线),Straight(直线),Flowchart(流程图),Statemachine(状态机)Connector:['Flowchart',{cornerRadius:5,alwaysRespectStubs:true,stub:5}],//鼠标不能拖动删除线ConnectionsDetachable:false,//删除线的时候节点不删除DeleteEndpointsOnDetach:false,//连线的端点//Endpoint:["Dot",{radius:5}],Endpoint:['Rectangle',{height:10,width:10}],//线端点的样式EndpointStyle:{fill:'rgba(255,255,255,0)',outlineWidth:1},LogEnabled:false,//是否打开jsPlumb的内部日志记录//绘制线PaintStyle:{stroke:'#409eff',strokeWidth:2},HoverPaintStyle:{stroke:'#409eff'},//绘制箭头Overlays:[['Arrow',{width:8,length:8,location:1}]],RenderMode:'svg'}//jsplumb连接参数exportconstjsplumbConnectOptions={isSource:true,isTarget:true,//动态锚点、提供了4个方向Continuous、AutoDefaultanchor:['TopCenter','RightMiddle','BottomCenter','LeftMiddle']}exportconstjsplumbSourceOptions={filter:'.node-anchor',//触发连线的区域/*"span"表示标签,".className"表示类,"#id"表示元素id*/filterExclude:false,anchor:['TopCenter','RightMiddle','BottomCenter','LeftMiddle'],allowLoopback:false}exportconstjsplumbTargetOptions={filter:'.node-anchor',/*"span"表示标签,".className"表示类,"#id"表示元素id*/filterExclude:false,anchor:['TopCenter','RightMiddle','BottomCenter','LeftMiddle'],allowLoopback:false}
在父组件引入配置文件和方法
import{jsplumbSetting,jsplumbConnectOptions,jsplumbSourceOptions,jsplumbTargetOptions}from'./config/commonConfig'
接下来在上面说的初始化方法文件里面配置鼠标滚轮缩放插件的方法 this.initPanZoom():
//鼠标滚动放大缩小initPanZoom(){constmainContainer=this.jsPlumb.getContainer()constmainContainerWrap=mainContainer.parentNodeconstpan=panzoom(mainContainer,{smoothScroll:false,bounds:true,//autocenter:true,zoomDoubleClickSpeed:1,minZoom:0.5,maxZoom:2,//设置滚动缩放的组合键,默认不需要组合键beforeWheel:(e)=>{//console.log(e)//letshouldIgnore=!e.ctrlKey//returnshouldIgnore},beforeMouseDown:function(e){//allowmouse-downpanningonlyifaltKeyisdown.Otherwise-ignorevarshouldIgnore=e.ctrlKeyreturnshouldIgnore}})this.jsPlumb.mainContainerWrap=mainContainerWrapthis.jsPlumb.pan=pan//缩放时设置jsPlumb的缩放比率pan.on('zoom',e=>{const{scale}=e.getTransform()this.jsPlumb.setZoom(scale)})pan.on('panend',(e)=>{})//平移时设置鼠标样式mainContainerWrap.style.cursor='grab'mainContainerWrap.addEventListener('mousedown',functionwrapMousedown(){this.style.cursor='grabbing'mainContainerWrap.addEventListener('mouseout',functionwrapMouseout(){this.style.cursor='grab'})})mainContainerWrap.addEventListener('mouseup',functionwrapMouseup(){this.style.cursor='grab'})},
大功告成,data的数据放在这里,测试使用:
{"FlowJson":{"nodeList":[{"type":"start","nodeName":"已新建","id":"start-HiXWf8wsAcrWXjAAXVWc6AQk00000001","node_code":"已新建","trigger_event":"","branch_flow":"","icon":"play-circle","x":175,"y":60,"width":50,"height":50},{"type":"freedom","nodeName":"待审批","id":"freedom-YakFJzZ5VSp3Gec6ZULD2JDK00000004","node_code":"待审批","trigger_event":"","branch_flow":"","icon":"sync","x":330,"y":160,"width":50,"height":120},{"type":"end","nodeName":"已通过","id":"end-JjRvtD5J2GIJKCn8MF7IYwxh00000999","node_code":"已通过","trigger_event":"","branch_flow":"","icon":"stop","x":330,"y":360,"width":50,"height":50},{"type":"end","nodeName":"审批拒绝","id":"end-J1DMScH5YjSKyk0HeNkbt62F00010001","node_code":"审批拒绝","trigger_event":"","branch_flow":"","icon":"stop","x":500,"y":350,"width":50,"height":50}],"linkList":[{"type":"link","id":"link-BpI6ZuX1bJywz5SEi3R5QaWoi7g3QiSr","sourceId":"start-HiXWf8wsAcrWXjAAXVWc6AQk00000001","targetId":"freedom-YakFJzZ5VSp3Gec6ZULD2JDK00000004","label":"LINE000000","role":[],"organize":[],"audit_role":[],"audit_organize":[],"audit_organize_same":"0","audit_dealer_same":"0","audit_dealers":[],"notice":"0","plug":"","pass_option":"pass","row_par_json":"","judge_fields":"","auth_at":"","auth_user":"","auth_stat":"","auth_mark":"","cls":{"linkType":"Flowchart","linkColor":"#008000","linkThickness":4}},{"type":"link","id":"link-5xJWzGlkIpUCsjmpfgesJxAOMHwkPlno","sourceId":"freedom-YakFJzZ5VSp3Gec6ZULD2JDK00000004","targetId":"end-J1DMScH5YjSKyk0HeNkbt62F00010001","label":"LINE000001","role":[],"organize":[],"audit_role":["PROJECT_SUPPORT_PLAN_CODE"],"audit_organize":[],"audit_organize_same":"0","audit_dealer_same":"0","audit_dealers":[],"notice":"0","plug":"","pass_option":"reject","row_par_json":"","judge_fields":"","auth_at":"","auth_user":"","auth_stat":"","auth_mark":"","cls":{"linkType":"Flowchart","linkColor":"#808080","linkThickness":1}},{"type":"link","id":"link-g05V3usXa86wAtpcMkvGzybdBlpasMjU","sourceId":"freedom-YakFJzZ5VSp3Gec6ZULD2JDK00000004","targetId":"end-JjRvtD5J2GIJKCn8MF7IYwxh00000999","label":"LINE000002","role":[],"organize":[],"audit_role":["PROJECT_SUPPORT_PLAN_CODE"],"audit_organize":[],"audit_organize_same":"0","audit_dealer_same":"0","audit_dealers":[],"notice":"0","plug":"","pass_option":"approve","row_par_json":"","judge_fields":"","auth_at":"","auth_user":"","auth_stat":"","auth_mark":"","cls":{"linkType":"Flowchart","linkColor":"#808080","linkThickness":1}}]}}
关于“vue+jsplumb实现工作流程图的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注恰卡编程网行业资讯频道,小编每天都会为大家更新不同的知识点。
推荐阅读
-
Vue组件的自定义事件和全局事件总线怎么使用
-
vue中消息订阅与发布如何使用
vue中消息订阅与发布如何使用这篇文章主要介绍“vue中消息订阅与...
-
Vue显示图片的方式有哪些
-
vue引入静态jquery报错如何解决
vue引入静态jquery报错如何解决这篇文章主要介绍“vue引入...
-
vue-cropper怎么实现裁剪图片
-
怎么用Vue+NodeJS实现大文件上传
-
Vue如何实现简易跑马灯效果
-
Vue怎么指定不编译的文件夹和favicon.ico
Vue怎么指定不编译的文件夹和favicon.ico这篇文章主要介...
-
Vue中的插槽怎么使用
-
Vue WebPack怎么忽略指定文件或目录