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

背景

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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那就可爱多一点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值