如何自己实现一个丝滑的流程图绘制工具(三)自定义挂载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: '
'
}) 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 } } },

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

你可能感兴趣的:(vue.js,流程图,前端)