一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

vue+jsplumb实现工作流程图代码示例

时间:2022-06-29 01:49:35 编辑:袖梨 来源:一聚教程网

本篇文章小编给大家分享一下vue+jsplumb实现工作流程图代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。

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

官网文档Home | jsPlumb Toolkit Documentation

先安装插件

npm install jsplumb --save

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

npm install panzoom --save

在需要的页面引入插件

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

接下来先写布局

父组件

flowNode是子组件

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

css;">

页面样式写完,接下来写插件配置

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、AutoDefault
  anchor: ['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.parentNode
    const 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 - ignore
        var shouldIgnore = e.ctrlKey
        return shouldIgnore
      }
    })
    this.jsPlumb.mainContainerWrap = mainContainerWrap
    this.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
              }
          }
      ]
  }
  
}

热门栏目