最近接到一个需求——给后台开发一个工作流程图,方便给领导看工作流程具体到哪一步。

先写了一个demo,大概样子如下:

官网文档Home | jsPlumb Toolkit Documentation

先安装插件

npm install jsplumb --save

安装panzoom,主要用于鼠标滚轮缩放流程图

npm install panzoom --save

在需要的页面引入插件

import panzoom from 'panzoom'
import { jsPlumb } from 'jsplumb'

接下来先写布局

父组件

<template><div class="workflow"><div class="flow_region"><div id="flowWrap" ref="flowWrap" class="flow-wrap" @drop="drop($event)" @dragover="allowDrop($event)"><div id="flow"><flowNode v-for="item in data.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"><div class="nodeName">{{ node.nodeName }}</div></div>
</template>

样式主要是子组件的,父组件样式随意就行

<style lang="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: 1px solid #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: 1px solid  #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(sandybrown 10%, white 30%, #9a54ff 60%);}.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: 1px dashed @labelColor;box-shadow: 0px 5px 9px 0px rgba(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 => {const res = () => { } // 此处可以添加是否创建连接的校验, 返回 false 则不添加;return res})this.loadEasyFlow()// 会使整个jsPlumb立即重绘。this.jsPlumb.setSuspendDrawing(false, true)})this.initPanZoom()},// 加载流程图loadEasyFlow() {// 初始化节点for (let i = 0; i < this.data.nodeList.length; i++) {const node = 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 (let i = 0; i < this.data.lineList.length; i++) {const line = this.data.lineList[i]const conn = 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配置信息,新建一个文件编写,具体如下:

export const jsplumbSetting = {grid: [10, 10],// 动态锚点、位置自适应anchor: ['TopCenter', 'RightMiddle', 'BottomCenter', 'LeftMiddle'],Container: 'flow',// 连线的样式 StateMachine、Flowchart,有四种默认类型:Bezier(贝塞尔曲线),Straight(直线),Flowchart(流程图),State machine(状态机)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连接参数
export const jsplumbConnectOptions = {isSource: true,isTarget: true,// 动态锚点、提供了4个方向 Continuous、AutoDefaultanchor: ['TopCenter', 'RightMiddle', 'BottomCenter', 'LeftMiddle']
}export const jsplumbSourceOptions = {filter: '.node-anchor', // 触发连线的区域/* "span"表示标签,".className"表示类,"#id"表示元素id*/filterExclude: false,anchor: ['TopCenter', 'RightMiddle', 'BottomCenter', 'LeftMiddle'],allowLoopback: false
}export const jsplumbTargetOptions = {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() {const mainContainer = this.jsPlumb.getContainer()const mainContainerWrap = mainContainer.parentNodeconst pan = panzoom(mainContainer, {smoothScroll: false,bounds: true,// autocenter: true,zoomDoubleClickSpeed: 1,minZoom: 0.5,maxZoom: 2,// 设置滚动缩放的组合键,默认不需要组合键beforeWheel: (e) => {// console.log(e)// let shouldIgnore = !e.ctrlKey// return shouldIgnore},beforeMouseDown: function(e) {// allow mouse-down panning only if altKey is down. Otherwise - ignorevar shouldIgnore = e.ctrlKeyreturn shouldIgnore}})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', function wrapMousedown() {this.style.cursor = 'grabbing'mainContainerWrap.addEventListener('mouseout', function wrapMouseout() {this.style.cursor = 'grab'})})mainContainerWrap.addEventListener('mouseup', function wrapMouseup() {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实现工作流程图相关推荐

  1. PHP网站工作流程图,在网站绘制工作流程图的教程分享(打工人必看)

    原标题:在网站绘制工作流程图的教程分享(打工人必看) 每一行.每一业都不是那么简单就能做顺手的,特别是要面对各种人际琐事的人事职员,要是不会一两招实用的办公技巧的话,可能很快便会被淘汰了.其中,学会绘 ...

  2. 工作流程怎么安排?用Edraw Max轻松创建工作流程图!

    思维导图软件推荐: MindManager XMind:ZEN TheBrain Edraw Max(亿图图示)是一款综合图形图表制作软件,它包含丰富的实例和模版,帮助您轻松创建流程图.网络拓扑图.组 ...

  3. 就业技术书文件表格_Word格式:工程预结算工作流程图及工作表单,附20余表格...

    在很多建筑单位,因为工程预结算的重要性,负责这块工作的基本上都是老板负责人的各种亲属,外面人基本上接触不到工作,不知道大家有没有见到这种公司呢? 工程预结算 正是因为工程预结算工作对建筑企业施工效益以 ...

  4. 变阻感器测量位移的计算机流程图,传感器工作流程图

    传感器是一种能把物理量或化学量转变成便于利用的电信号的器件,通常由敏感元件和转换元件组成.以下是学习啦小编为大家整理的关于传感器工作流程图,给大家作为参考,欢迎阅读! 传感器工作流程图 几种传感器的工 ...

  5. 销售流程图_工作流程图网络图模板,招聘销售合同库存,完整设计拿来就用

    Hello大家好,我是帮帮.今天跟大家分享一组工作流程图模板,招聘销售合同库存,完整设计拿来就用. 为了让大家能更稳定的下载模板,我们又开通了全新下载方式(见文章末尾),以便大家可以轻松获得免费模板和 ...

  6. 怎么添加流程图画布_工作流程图软件,教你绘制简单的工作流程图!

    工作流程图是用特定符号表述工作事项顺序的一种图示,它可以帮助管理者更好的了解实际工作内容,去除掉.合并多余环节,从而提高工作效率.事实上,流程图的种类有很多,常见的有程序流程图.工艺流程图和数据流程图 ...

  7. sp烘焙流程_烘焙工作流程图

    烘焙工作流程图 [相关阅读] 烘焙学基础篇 烘焙是门学问.根据字意的解释,"烘"是用火烘干湿物,例如 烘干;"焙"是用微火烘烤东西,例如焙茶;"烤&q ...

  8. 学校食堂工作流程图流程图模板分享

    学校食堂里面的工作是比较严谨的,所以对任何事情的要求就会比较高,那在学校食堂里面工作有哪些流程呢?下面是分享的食堂工作流程图模板,想要了解新知识的朋友可以进行了解. 学校食堂工作流程图-迅捷流程图 模 ...

  9. 分享招聘工作流程图模板及绘制技巧

    员工是企业宝贵的资源,招聘的目的绝不是简单地吸引大批应聘者,人力资源的根本目的是获得企业所需的人员,减少不必要的人员流失,同时招聘还存在潜在的目的:梳理企业形象,那么,大家知道招聘的具体流程是什么吗? ...

最新文章

  1. Fckeditor PHP/ASP File Upload Vul
  2. log4j:WARN Error initializing output writer. log4j:WARN Unsupported encoding?
  3. 4.性能下降原因和常见的Join查询
  4. [Android Pro] AndroidStudio IDE界面插件开发(进阶篇之Action机制)
  5. uniapp禁止遮罩层下的页面滚动
  6. JNI基础 c语言调用java方法
  7. 线性规划图解法求最优解_高中数学:简单的线性规划问题
  8. 费城中餐馆奇葩鸡翅定价引爆网络,数万网友想要破解数学谜题
  9. YankNote 笔记软件比 Sublime 好用吗
  10. 解决Manjaro系统安装MindMaster思维导图用不了(登录不了的问题)的问题,以及代替的方案
  11. altera/xlinx pcie dma应用
  12. 7-4 换硬币(20 分)
  13. 10分钟搭建一个免费个人博客网站
  14. 怎么修改图片的kb大小?如何缩小照片kb?
  15. 遗传算法 python 简书_基于DEAP库的Python进化算法从入门到入土—(二)简单遗传算法实现...
  16. arm服务器测评_ARM搭建我的世界服务器教程,适用于树莓派
  17. golang中的xg作用
  18. 机器学习4. 贝叶斯
  19. 第十五届智能车入门浅谈
  20. 【Android -- UI开发】一份 UI 开发学习指南

热门文章

  1. 【笔记】95%置信区间:一般我们用中括号[a,b]表示样本估计总体平均值误差范围的区间,a、b的具体数值取决于你对于“该区间包含总体均值“这一结果的可信程度,因此[a,b]被称为置信区间
  2. ISCC 2021 部分题目WP
  3. Mac上安装与使用MYSQL
  4. php怎么登录后显示用户名和密码错误,首页登录后怎么在首页显示用户名以及隐藏登录框?...
  5. [dbnmpntw]连接忙碌中_岳阳连接线7公里处 藏了一个“稀世”屋场
  6. MATLAB视频运动目标检测参考源码
  7. nuxt全栈仿美团官网13——首页下面的格调
  8. 使用纳米孔测序数据进行16S-DNA条形码研究的计算方法[综述]
  9. ext 两个grid横向排列_Intel新研究:180°横向FOV的曲面VR光学模组,体积缩减二分之一...
  10. 加密算法 之一:CMAC