如何自己实现一个丝滑的流程图绘制工具(三)自定义挂载vue组件

news/2024/5/18 21:30:27 标签: vue.js, 流程图, 前端

背景

bpmn-js是个流程图绘制的工具,但是现在我希望实现的是,绘制的不是节点而是一个vue组件。
保留线的拖拽和连接。

方案

那就说明不是依赖于节点的样式,找到了他有个属性,就是类似覆盖节点的操作。
思路就是用vue组件做遮罩,盖住原本的节点样式。

/**
     * 批量操作节点
     */
    handleAddOverlay() {
      const bpmnModeling = this.bpmnModeler.get('modeling')
      const contextPad = this.bpmnModeler.get('contextPad')
      this.bpmnModeler.on('import.done', () => {
        // 加载完成后每个元素遍历
        const elementRegistry = this.bpmnModeler.get('elementRegistry')
        elementRegistry.forEach(element => {
          if (['bpmn:Task'].includes(element.type)) {
            const parent = elementRegistry.getGraphics(element)

            bpmnModeling.resizeShape(element, {
              width: element.width || this.config.width || 60,
              height: element.height || this.config.height || 60,
              x: getDi(element).bounds.x,
              y: getDi(element).bounds.y
            })
            // 遍历任务节点,为每个节点添加 overlays
            if (this.isShowComponent) {
              bpmnModeling.setColor(element, { stroke: this.config.borderColor || '#eee' }) // 修改边框颜色
              bpmnModeling.setColor(element, { fill: this.config.fillColor || '#fff' }) // 修改边框颜色
              this.addOverlay(element, parent)
            }
          } 
        })
      })
    },

接下来是挂载覆盖物的重点,如何让覆盖物跟随节点的移动而移动

/**
     *
     * @param {*} element
     * 增加覆盖物节点操作
     */
    addOverlay(element, parent) {
      const __this = this
      const overlays = this.bpmnModeler.get('overlays')
      const bpmnModeling = this.bpmnModeler.get('modeling')
      const elementRegistry = this.bpmnModeler.get('elementRegistry')
      const index = this.data.nodeLists.findIndex(item => item.config.id === element.id)

      // 添加覆盖物 ------------------------------------- begin
      overlays.add(element, 'my-overlay', {
        position: __this.overlayPosition,
        show: {
          minZoom: 0.1
        },
        html: '<div id="my-component"></div>'
      })
      const Profile = Vue.extend(this.config.components)
      overlays.get({ element: element, type: 'my-overlay' })[0].htmlContainer.id = element.id

      new Profile({
        router,
        propsData: {
          element: element,
          node: index > -1 ? this.data.nodeLists[index] : {},
          func: this.func,
          ...this.props
        },
        mounted() {
          const component = this
          // 绑定鼠标按下事件
          component.$el.addEventListener('mousedown', event => {
            __this.isDrag = false
            event.preventDefault()
            if (!__this.disable) {
              dragMouseDown(event)
            }
          })
          // 自定义组件点击事件
          component.$el.addEventListener('click', () => {
            if (!__this.isDrag) {
              __this.showContextPad(element)
              const bpmnElement = elementRegistry.get(element.id)
              __this.currentElement = bpmnElement
              __this.$emit('click', bpmnElement) // 点击事件
            }
          })
        }
      }).$mount('#my-component')
      // 添加覆盖物 -------------------------------------end

      // 必须作为公共变量进行值更改
      let pos1 = 0
      let pos2 = 0
      let pos3 = 0
      let pos4 = 0

      /**
       *
       * @param {*} e
       * @param {*} overlayPosition
       * 鼠标按下开始
       */
      function dragMouseDown(e) {
        e = e || window.event
        e.preventDefault()
        pos3 = e.clientX
        pos4 = e.clientY
        document.onmousemove = event => {
          __this.isDrag = true
          elementDrag(event, __this.overlayPosition)
        }
        document.onmouseup = () => {
          __this.currentElement = null
          document.onmouseup = null
          document.onmousemove = null
        }
      }

      /**
       *
       * @param {*} e
       * @param {*} overlayPosition
       *  节点的拖拽
       */
      function elementDrag(e, overlayPosition) {
        e = e || window.event
        e.preventDefault()
        // 计算新的元素位置
        pos1 = pos3 - e.clientX
        pos2 = pos4 - e.clientY
        pos3 = e.clientX
        pos4 = e.clientY

        const bpmnElement = elementRegistry.get(element.id)
        const deltaX = overlayPosition.x + pos1
        const deltaY = overlayPosition.y + pos2

        // 移动父节点及其连接线
        moveParentNode(bpmnElement, deltaX, deltaY)

     }

      /**
       *
       * @param {*} element
       * @param {*} dx
       * @param {*} dy
       * 更改父节点操作
       */
      function moveParentNode(element, dx, dy) {
        const parent = element.parent
        if (!parent) {
          return
        }
        // // 更新父节点的位置信息
        bpmnModeling.moveElements([element], { x: -dx, y: -dy }, null)
        // 更新覆盖物的位置
        const overlay = overlays.get({ element: parent, type: 'my-overlay' })
        overlay.position = {
          top: overlay.top - dy,
          left: overlay.left - dx
        }
      }
    },

在这里插入图片描述


http://www.niftyadmin.cn/n/4966438.html

相关文章

[Stable Diffusion教程] 第一课 原理解析+配置需求+应用安装+基本步骤

第一课 原理解析配置需求应用安装基本步骤 本次内容记录来源于B站的一个视频 以下是自己安装过程中整理的问题及解决方法&#xff1a; 问题&#xff1a;stable-diffusion-webui启动No Python at ‘C:\xxx\xxx\python.exe‘ 解答&#xff1a;打开webui.bat 把 if not de…

开源与专有软件:比较与对比

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

单片机UART一对多:同时读取多个传感器基于modbus协议

文章目录 背景MODBUS协议介绍UART接口改一对多参考链接 背景 很多传感器现在都做成了串口模块&#xff0c;如激光测距传感器TOF050&#xff0c;在开发时使用串口功能模块不仅大大加快了我们的开发进度&#xff0c;还能降低功能模块直接的耦合度&#xff0c;专业是功能交给专业…

pgadmin4中的备份与恢复

一&#xff0c;postgresql 数据的备份与恢复 &#xff08;一&#xff09;数据库备份与恢复 1&#xff0c;备份 windows环境 1> dump 逻辑备份 1&#xff0c;用管理员身份打开power shell 2&#xff0c;切换到本机 postgresql 安装目录下的 bin 目录&#xff1a; PS C…

视频集中存储/云存储平台EasyCVR国标GB28181协议接入的报文交互数据包分析

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理…

MongoDB Long 类型 shell 查询

场景 1、某数据ID为Long类型&#xff0c;JAVA 定义实体类 Id Long id 2、查询数据库&#xff0c;此数据存在 3、使用 shell 查询&#xff0c;查不到数据 4、JAVA代码查询Query.query 不受任何影响 分析 尝试解决&#xff08;一&#xff09; long 在 mongo中为 int64 类型…

关于python from .. import .. 以及 pycharm对于source root bug的一个通用解决方案

先说问题 python里默认from .. import .. 这个写法的from会查找当前文件夹下但不包含当前文件夹的路径&#xff0c;也就是说 如果from ..的这里写入的是当前文件夹 是会报错的&#xff0c;因为无法找到当前文件夹。 尝试的坑 pycharm的source root。这个是真的坑啊。加了source…

Linux —— keepalived

简介 Keepalived 是一个用 C 语言编写的路由软件。这个项目的主要目标是为 Linux 系统和基于 Linux 的基础设施提供简单而强大的负载均衡和高可用性功能。 Keepalived 开源并且免费的软件。 Keepalived 的2大核心功能 1. loadbalance 负载均衡 LB&#xff1a;ipvs--》lvs软件…