1. 程式人生 > >vue專案中使用bpmn-自定義platter

vue專案中使用bpmn-自定義platter

內容概述

本系列“vue專案中使用bpmn-xxxx”分為七篇,均為自己使用過程中用到的例項,手工原創,目前陸續更新中。主要包括vue專案中bpmn使用例項、應用技巧、基本知識點總結和需要注意事項,具有一定的參考價值,需要的朋友可以參考一下。如果轉載或通過爬蟲直接爬的,格式特別醜,請來原創看:我是作者原文

前情提要

經過前四篇的學習,我們能夠實現bpmn基本繪圖、預覽、為節點加事件加顏色等效果,這一篇我們來說,如何自定義左側工具欄(platter),首先看一下自定義前後效果圖對比:

我們本次要實現的目標:基於左側platter原有元素型別,創建出一個新的自定義節點。暫且叫它“草莓蛋糕”節點,型別是 bpmn:Task, 樣式我們自己找一個好看的小草莓蛋糕圖案。所以,開動吧~首先新建一個“customPalette”資料夾,裡面放我們今天所有自定義的檔案。

步驟1:建立platter類函式,命名為CustomPalette.js

export default class CustomPalette {
  constructor(create, elementFactory, palette) {
    this.create = create;
    this.elementFactory = elementFactory;
    palette.registerProvider(this);
  }
 
 
  // 這個是繪製palette的核心,函式名不要變
  getPaletteEntries() {
    const elementFactory = this.elementFactory;
    const create = this.create;
 
    function dragEventFactory(type) {
      return function (event) {
        const taskShape = elementFactory.create('shape', {
          type: type
        });
        create.start(event, taskShape);
      };
    }
 
    return {
      'create.cake': {
        title: '我是自定義節點-草莓蛋糕',    // 滑鼠懸浮到節點上顯示的文字
        className: 'icon-custom bpmn-icon-cake',   // 樣式名
        action: {      // 操作該節點時會觸發的事件,此時只註冊一個拖動事件即可,否則拖動時沒有效果
          dragstart: dragEventFactory('bpmn:Task')
        }
      }
    };
  }
}
CustomPalette.$inject = [
  'create',
  'elementFactory',
  'palette'
];
View Code

此時,我們已經註冊好了一個名稱為“create.cake”的節點,拖動它時,畫布中會出現一個"bpmn:Task"型別的節點,此時需要將該檔案匯出並在頁面中引入,否則沒有效果。

步驟2:在CustomPalette.js同級,建立一個index.js檔案將其匯出

import CustomPalette from './CustomPalette';
export default {
  __init__: ['customPalette']
  customPalette: ['type', CustomPalette],
};

步驟3:頁面中(index.vue)引入index.js

import customModule from './customPalette';
export default {
  mounted() {
    this.containerEl = document.getElementById('container');
    this.bpmnModeler = new BpmnModeler({
       additionalModules: [ customModule ]
    });
}

步驟4:為節點定義樣式

新建一個customPalette.scss檔案,在該檔案同級放一張“cake.png”的圖片,作為節點的背景圖寫入。背景圖引入的話,貌似只支援.png格式,親測:jpg報錯

.bpmn-icon-cake {
  background-image: url('./cake.png');
}
 
.icon-custom {
  background-size: 65%;
  background-repeat: no-repeat;
  background-position: center center;
}

並且在main.js中引入,注意,一定要在main.js中全域性引入,否則不生效。

import 'customPalette/customPalette.scss';

此時,我們便可以在左側工具欄中看到自定義的“草莓蛋糕”節點了,但是此時拖動該節點,右側只會產生一個“bpmn:Task”的節點,只有一個框框。

我們希望的是,拖動後畫布中也顯示自定義圖示,所以我們進行下一步:自定義渲染

步驟5:畫布渲染自定義節點

此時需要我們新建一個 CustomRenderer.js檔案,作用:自定義 renderer。因為我們是在bpmn原有的元素“bpmn:Task”基礎上進行修改,所以我們需要對將BaseRenderer進行繼承。

import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; // 引入預設的renderer
 
const HIGH_PRIORITY = 1500; // 最高優先順序
 
export default class CustomRenderer extends BaseRenderer {
  // 繼承BaseRenderer
  constructor(eventBus, bpmnRenderer) {
    super(eventBus, HIGH_PRIORITY);
    this.bpmnRenderer = bpmnRenderer;
  }
 
  canRender(element) {
    return !element.labelTarget;
  }
 
  drawShape(parentNode, element) {
    const shape = this.bpmnRenderer.drawShape(parentNode, element);
    return shape;
  }
 
  getShapePath(shape) {
    return this.bpmnRenderer.getShapePath(shape);
  }
}
 
CustomRenderer.$inject = ['eventBus', 'bpmnRenderer'];
View Code

此時, CustomRenderer.js檔案大概結構完成了,注意:HIGH_PRIORITY變數和canRender不可以刪掉,否則會有問題。重頭戲是裡面的drawShape函式。

步驟6:書寫drawShape函式

我們在CustomRenderer.js同級建立一個util檔案,記錄自定義型別節點的一些屬性。

import cake from './cake.png';

// 自定義元素的型別,此時我們只需要自定義一種節點,所以陣列只有一個元素
const customElements = ['bpmn:Task']; 
const customConfig = {
  // 自定義元素的配置
  cake: {
    url: cake,
    attr: {x: 0, y: 0, width: 50, height: 50}
  }
};
 
export {customElements, customConfig};

現在我們來書寫drawShape函式

import { customElements, customConfig } from './util';
import { append as svgAppend, create as svgCreate } from 'tiny-svg';
...
drawShape(parentNode, element) {
  const type = element.type; // 獲取到型別
  // 所有節點都會走這個函式,所以此時只限制,需要自定義的才去自定義,否則仍顯示bpmn預設圖示
  if (customElements.includes(type)) {  
    const {url, attr} = customConfig['cake'];
    const customIcon = svgCreate('image', {...attr, href: url});
    element['width'] = attr.width;
    element['height'] = attr.height;
    svgAppend(parentNode, customIcon);
    return customIcon;
  }
  const shape = this.bpmnRenderer.drawShape(parentNode, element);
  return shape;
}

步驟7: 匯出並使用CustomRenderer

修改之前匯出CustomPalette的 index.js檔案

import CustomPalette from './CustomPalette';
import CustomRenderer from './CustomRenderer';
 
export default {
  __init__: ['customPalette', 'customRenderer'],
  customPalette: ['type', CustomPalette],
  customRenderer: ['type', CustomRenderer]
};

注意:此時__init__內的屬性名都不可以改,不要問為什麼,因為改了報錯。

步驟3中已經將該index.js引入到了頁面中,此時無需再次引入,此時我們來看看效果。

 後續

專案目錄:index.vue是畫布主頁面,同級customPalette資料夾下共有6個檔案,結構如下:

 

各個檔案的程式碼片段在文中已經展示過了,資料夾不知道怎麼上傳到部落格。如想獲取完整原始碼或有問題,公眾號聯絡我,掃下面二維碼或公眾號搜“Lemoncool”,即可獲取~

 可愛的你可能還需要

  • vue專案中使用bpmn-為節點新增顏色
  • vue專案中使用bpmn-節點篇(為節點新增點選事件、根據id找節點例項、更新節點名字、獲取指定型別的所有節點)
  • vue專案中使用bpmn-流程圖預覽篇
  • vue專案中使用bpmn-基礎篇