Bpmn.js 中文文檔(一)

Bpmn.js 中文文檔


因爲工做須要(其實不是很須要),在公司項目的基礎上開源了一個基於 bpmn-js + Vue 2.x + ElementUI 的一個流程編輯器 Bpmn Process Designer, 預覽地址 MiyueFE blog, 歡迎 fork 和 star。
文章首發於 掘金 Bpmn.js 中文文檔(一),轉載請註明出處。

一. 引入Bpmn.js並初始化建模器

/* 基於vue2.x, 省略了template模板與部分data */

import BpmnModeler from "bpmn-js/lib/Modeler"

export default {
    methods: {
        initModeler() {
            this.bpmnModeler = new BpmnModeler({
                container: document.getElementById("bpmn-container")
            })
        }
    },
    mounted() {
        this.initModeler();
    }
}

進入到源文件Modeler.js,能夠找到建立Modeler建模器的時候需的參數。javascript

this.bpmnModeler = new BpmnModeler(options: Options);

interface Options {
    container: DomElement; // 渲染容器
    width:string | number;// 查看器寬度
    height: string | number; // 查看器高度
    moddleExtensions: object;// 須要用的擴展包
    modules:<didi.Module>[]; // 自定義且須要覆蓋默認擴展包的模塊列表
    additionalModules: <didi.Module>[]; // 自定義且與默認擴展包一塊兒使用的模塊列表
}

初始化完成以後,在控制檯打印this.bpmnModeler,能夠發現BpmnModeler類繼承了多個基礎類。css

Modeler
    -> BaseModeler
        -> BaseViewer
            -> Diagram
                -> Object

Bpmn.js提供的默認擴展包名稱,能夠在this.bpmnModeler.__proto__._modules內找到,一共開放了32個擴展包。擴展包名稱能夠在this.bpmnModeler.injector._providers內,包名即鍵名。html

須要調用這些擴展包時,可使用以下方式:vue

const xxxModule = this.bpmnModeler.get("xxx"); // xxx表明擴展包名稱

Modeler實例化以後可直接調用的方法:java

/**
 * 返回name對應的模塊實例
 * @param { string } name 模塊名
 * @param { boolean } strict 啓用嚴格模式。false:缺乏的模塊解析爲null返回;true:拋出異常
 */
this.bpmnModeler.get(name, strict);

// 建立空白流程圖
// 內部調用了importXML方法,讀取內部的默認xml字符串
this.bpmnModeler.createDiagram();

// 將圖形dom掛載到目標節點
this.bpmnModeler.attachTo(parentNode);

// 清空
this.bpmnModeler.clear()

// 銷燬
this.bpmnModeler.destroy()

// 脫離dom
this.bpmnModeler.detach()

// 獲取流程定義
this.bpmnModeler.getDefinitions()

// 獲取擴展功能模塊列表
this.bpmnModeler.getModules()

/**
 * 導入解析的定義並呈現BPMN 2.0圖。完成後,查看器將結果報告回給提供的回調函數(錯誤,警告)
 * @param { ModdleElement<Definitions> } definitions 模塊名
 * @param { ModdleElement<BPMNDiagram>|string } [bpmnDiagram] 要呈現的BPMN圖或圖的ID(若是未提供,將呈現第一個)
 */
this.bpmnModeler.importDefinitions(definitions, bpmnDiagram)

/**
 * 導入xml(字符串形式),返回導入結果
 * 後續會取消傳入回調函數的方式
 * 推薦使用async/await或者鏈式調用
 * @param { string } xml 流程圖xml字符串
 * @param { Promise } callback 回調函數,出錯時返回{ warnings,err }
 */
this.bpmnModeler.importXML(xml, callback)

// 註銷事件監聽器
this.bpmnModeler.off(eventName, callback)

// 註冊事件監聽,同名將刪除之前的監聽器,privorty可不傳,程序會自動替換回調函數
this.bpmnModeler.on(eventName, priority, callback, target)

// em。。。不瞭解
this.bpmnModeler.open()

// 保存爲svg文件,與importXML方法同樣,後續會取消傳入callback的方式
this.bpmnModeler.saveSVG(callback)

// 保存爲xml文件,與importXML方法同樣,後續會取消傳入callback的方式
this.bpmnModeler.saveXML(callback)

二. 基礎功能

使用過程當中,經常使用的組件主要包含:palette 左側元素欄、 contentPad 元素操做塊、 propertiesPanel右側元素屬性編輯欄git

1. palette 與 contentPad

這兩個組件在實例化建模器的時候已經渲染到了頁面上,只須要引入對應的樣式文件便可。github

import "bpmn-js/dist/assets/diagram-js.css";
import "bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
import "bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";

2. propertiesPanel

使用這個組件須要在實例化建模器時修改配置項,並引入對應樣式文件typescript

import "bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css"; // 右邊工具欄樣式

import propertiesPanelModule from "bpmn-js-properties-panel";
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";

export default {
    methods: {
        initModeler() {
            this.bpmnModeler = new BpmnModeler({
                container: document.getElementById("bpmn-container"),
                propertiesPanel: {
                  parent: "#attrs-panel"
                },
                additionalModules: [ propertiesPanelModule, propertiesProviderModule ]
            })
        }
    },
    mounted() {
        this.initModeler();
    }
}

3. 漢化

在漢化以前,能夠在github或者碼雲上找到不少大佬的翻譯文件,將翻譯文件下載下載保存到本地。canvas

// 1. 建立翻譯文件 zh.js(命名隨意),導出英文關鍵字對應的中文翻譯
export default {
    "Append EndEvent": "追加結束事件",
    "Append Gateway": "追加網關",
    "Append Task": "追加任務",
    "Append Intermediate/Boundary Event": "追加中間拋出事件/邊界事件",
    ...
}
    
// 2. 創建翻譯模塊方法customTranslate.js
import translations from "./zh";

export default function customTranslate(template, replacements) {
  replacements = replacements || {};

  // Translate
  template = translations[template] || template;

  // Replace
  return template.replace(/{([^}]+)}/g, function(_, key) {
    let str = replacements[key];
    if (
      translations[replacements[key]] !== null &&
      translations[replacements[key]] !== "undefined"
    ) {
      // eslint-disable-next-line no-mixed-spaces-and-tabs
      str = translations[replacements[key]];
      // eslint-disable-next-line no-mixed-spaces-and-tabs
    }
    return str || "{" + key + "}";
  });
}

// 3. 在實例化建模器時以自定義模塊的方式傳入參數
import customTranslate from "./pugins/customTranslate";

export default {
  methods: {
    initModeler() {
        this.bpmnModeler = new BpmnModeler({
            container: document.getElementById("bpmn-container"),
            additionalModules: [
                { translate: ["value", customTranslate] }
            ]
        })
    }
  }
}
翻譯文件來自碼雲,可是忘記了做者的信息了,若是做者發現請您聯繫我更改或者刪除

4. 其餘功能(非自定義的功能模塊配置項)

添加鍵盤快捷鍵:數組

this.bpmnModeler = new BpmnModeler({
    container: document.getElementById("bpmn-container"),
    keyboard: {
        bindTo: document // 或者window,注意與外部表單的鍵盤監聽事件是否衝突
    }
});

三. 事件

Bpmn.js 提供了EventBus事件總線模塊來管理監聽事件,並預設了244個事件。

下面的元素對象指包含element元素的對象,其餘屬性不定(部分事件返回的對象也不包含element)。

「 - 」 短橫線表示暫時沒有找到什麼時候觸發該事件

如下事件都可使用this.bpmnModeler.on(eventName, callback)或者eventBus.on(eventName, callback)的形式註冊。

// 經過事件總線發出的事件
interface InternalEvent {
    type: string; // 發生的事件名稱,可是很快會被置爲undefined
    element: Shape | Connection;
    elements: Element[];
    shape: Shape;
    context: object; // 有點複雜,有興趣的朋友能夠研究
    gfx?: SVGElement;
    svg?: SVGElement;
    viewport?: SVGElement;
    viewbox?: Viewbox;
    pad?: object; // 見 Element.pad
}

interface Element {
    element: Shape | Connection;
    gfx?: SVGElement;
    pad?: {
        id: string;
        html: DOMElement;
        position: { right: number; top: number };
        scale: { max: number; min: number };
        show: object | null;
        type: string; // 通常是"context-pad"
    }
}

interface Elements {
    elements: Array<Shape | Connection>
}

interface Canvas {
    svg?: SVGElement;
    viewport?: SVGElement;
}

interface Viewbox {
    viewbox: {
        height: number;
        width: number;
        x: number;
        y: number;
        inter: object; // 包含x,y,width,height的一個對象
        outer: object; // 包含x,y,width,height的一個對象
        scale: number; // 當前縮放比例(小數)
    }
}
序號 事件名 說明 callback參數
0 "diagram.destroy" 流程編輯器銷燬 event:InternalEvent
1 "render.shape" 調用GraphicsFactory.drawShape時觸發,開始渲染形狀
2 "render.connection" 調用GraphicsFactory.drawConnection時觸發,開始渲染連線
3 "render.getShapePath" 調用GraphicsFactory.getShapePath時觸發,開始獲取形狀路徑
4 "render.getConnectionPath" 調用GraphicsFactory.getConnectionPath時觸發
5 "diagram.init" 指示畫布已準備好在其上進行繪製
6 "shape.added" 已更新到xml內,觸發渲染方法,返回值爲插入的新元素 event:InternalEvent, element: Element
7 "connection.added" 已更新到xml內,觸發渲染方法,返回值爲插入的新元素 event:InternalEvent, element: Element
8 "shape.removed" 形狀移除完成,返回值爲被移除元素 event:InternalEvent, element: Element
9 "connection.removed" 連線移除完成,返回值爲被移除元素
10 "elements.changed" 元素髮生改變並更改完成 event: InternalEvent, element: Elements
11 "diagram.clear" 流程編輯器元素及畫布已清空 event:InternalEvent
12 "canvas.destroy" 畫布銷燬 event:InternalEvent
13 "canvas.init" 畫布初始化完成
14 "shape.changed" 形狀屬性更新,返回當前元素 event:InternalEvent, element: Element
15 "connection.changed" 連線屬性更新,返回當前元素 event:InternalEvent, element: Element
16 "interactionEvents.createHit" shape.added,connection.added以後觸發
17 "interactionEvents.updateHit" shape.changed,connection.changed以後觸發
18 "shape.remove" 形狀被選中移除,返回被移除的元素對象 event:InternalEvent, element: Element
19 "connection.remove" 連線被選中移除 event:InternalEvent, element: Element
20 "element.hover" 鼠標移動到元素上,返回鼠標位置處元素對象 event:InternalEvent, element: Element
21 "element.out" 鼠標移出元素,返回鼠標最近移入的元素對象 event:InternalEvent, element: Element
22 "selection.changed" 選中元素變化時,返回新選中的元素對象 event:InternalEvent, element: Element
23 "create.end" 從palette中新建的元素建立完成(不清楚爲何有兩個相同的參數) event:InternalEvent, event:InternalEvent
24 "connect.end" 從palette中或者從選中節點中新建的連線元素建立完成(不清楚爲何有兩個相同的參數) event:InternalEvent, event:InternalEvent
25 "shape.move.end" 形狀元素移動結束後 event:InternalEvent, element: Element
26 "element.click" 元素單擊事件 event:InternalEvent, element: Element
27 "canvas.viewbox.changing" 視圖縮放過程當中 event:InternalEvent
28 "canvas.viewbox.changed" 視圖縮放完成 event:InternalEvent, viewbox: Viewbox
29 "element.changed" 元素髮生改變時觸發,返回發生改變的元素 event:InternalEvent, element: Element
30 "element.marker.update" 元素標識更新時觸發
31 "attach" 畫布或者根節點從新掛載時
32 "detach" 畫布或者根節點移除掛載時
33 "editorActions.init" 流程編輯模塊加載完成
34 "keyboard.keydown" 鍵盤按鍵按下
35 "element.mousedown" 鼠標在元素上按下時觸發 event:InternalEvent, element: Element
36 "commandStack.connection.start.canExecute" 連線開始時檢測是否能夠建立連線,點擊建立連線的按鈕時觸發
37 "commandStack.connection.create.canExecute" 連線開始時檢測是否能夠建立連線,
38 "commandStack.connection.reconnect.canExecute" 檢測連線是否能夠修改
39 "commandStack.connection.updateWaypoints.canExecute" 檢測是否能夠更新連線拐點
40 "commandStack.shape.resize.canExecute" 檢測形狀是否能夠更改大小
41 "commandStack.elements.create.canExecute" 檢測是否能夠建立元素
42 "commandStack.elements.move.canExecute" 檢測是否能夠移動元素
43 "commandStack.shape.create.canExecute" 檢測是否能夠建立形狀
44 "commandStack.shape.attach.canExecute" 檢測元素是否能夠掛載到目標上
45 "commandStack.element.copy.canExecute" 檢測元素是否能夠被複制
46 "shape.move.start" 形狀開始移動 event:InternalEvent, element: Element
47 "shape.move.move" 形狀移動過程當中 event:InternalEvent, element: Element
48 "elements.delete" 元素被刪除,返回被刪除的元素 event:InternalEvent, element: Element
49 "tool-manager.update"
50 "i18n.changed"
51 "drag.move" 元素拖拽過程當中 event:InternalEvent, event:InternalEvent
52 "contextPad.create" 當contextPad出現的時候觸發 event:InternalEvent, element: Element
53 "palette.create" 左側palette開始建立
54 "autoPlace.end" 自動對齊結束
55 "autoPlace" 觸發自動對齊方法時
56 "drag.start" 元素拖拽開始 event:InternalEvent, event:InternalEvent
57 "drag.init" 點擊了元素即將進行拖拽(包括點擊palette和畫布內的元素) event:InternalEvent, event:InternalEvent
58 "drag.cleanup" 元素拖拽結束 event:InternalEvent, event:InternalEvent
59 "commandStack.shape.create.postExecuted" 當建立形節點的時候觸發 event:InternalEvent, event:InternalEvent
60 "commandStack.elements.move.postExecuted" 當元素移動的時候觸發 event:InternalEvent, event:InternalEvent
61 "commandStack.shape.toggleCollapse.postExecuted" 當可摺疊的節點展開/摺疊的時候觸發 event:InternalEvent, event:InternalEvent
62 "commandStack.shape.resize.postExecuted" 當節點大小發生改變的時候觸發 event:InternalEvent, event:InternalEvent
63 "commandStack.element.autoResize.canExecute" 當節點大小發生自動調整的時候觸發 event:InternalEvent, event:InternalEvent
64 "bendpoint.move.hover" 鼠標點擊連線折點並進行移動時觸發 event:InternalEvent, event:InternalEvent
65 "bendpoint.move.out" 返回時間不定,可能在拖動時觸發,也可能在拖動過程當中 event:InternalEvent, event:InternalEvent
66 "bendpoint.move.cleanup" 鼠標點擊連線折點時或者移動折點完成 event:InternalEvent, event:InternalEvent
67 "bendpoint.move.end" 鼠標點擊連線折點並移動完成 event:InternalEvent, event:InternalEvent
68 "connectionSegment.move.start" 鼠標選中連線進行拖動開始 event:InternalEvent, event:InternalEvent
69 "connectionSegment.move.move" 鼠標選中連線進行拖動過程當中 event:InternalEvent, event:InternalEvent
70 "connectionSegment.move.hover" 鼠標選中連線進行拖動開始 event:InternalEvent, event:InternalEvent
71 "connectionSegment.move.out" 鼠標選中連線,按下鼠標時 event:InternalEvent, event:InternalEvent
72 "connectionSegment.move.cleanup" 鼠標選中連線後放開鼠標時 event:InternalEvent, event:InternalEvent
73 "connectionSegment.move.cancel" 選中連線以後取消鏈接 event:InternalEvent, event:InternalEvent
74 "connectionSegment.move.end" 選中連線並拖拽結束 event:InternalEvent, event:InternalEvent
75 "element.mousemove" 鼠標移除元素後
76 "element.updateId" 更新元素id時觸發
77 "bendpoint.move.move" 連線上的拐點被拖拽移動時觸發
78 "bendpoint.move.start" 連線上的拐點被拖拽移動開始時觸發
79 "bendpoint.move.cancel" 連線上的拐點被點擊並取消拖拽
80 "connect.move" 連線被移動時
81 "connect.hover"
82 "connect.out"
83 "connect.cleanup"
84 "create.move"
85 "create.hover"
86 "create.out"
87 "create.cleanup"
88 "create.init"
89 "copyPaste.copyElement"
90 "copyPaste.pasteElements"
91 "moddleCopy.canCopyProperties"
92 "moddleCopy.canCopyProperty"
93 "moddleCopy.canSetCopiedProperty"
94 "copyPaste.pasteElement"
95 "popupMenu.getProviders.bpmn-replace"
96 "contextPad.getProviders"
97 "resize.move"
98 "resize.end"
99 "commandStack.shape.resize.preExecute"
100 "spaceTool.move"
101 "spaceTool.end"
102 "create.start"
103 "commandStack.connection.create.postExecuted"
104 "commandStack.connection.layout.postExecuted"
105 "shape.move.init"
106 "resize.start"
107 "resize.cleanup"
108 "directEditing.activate"
109 "directEditing.resize"
110 "directEditing.complete"
111 "directEditing.cancel"
112 "commandStack.connection.updateWaypoints.postExecuted"
113 "commandStack.label.create.postExecuted"
114 "commandStack.elements.create.postExecuted"
115 "commandStack.shape.append.preExecute"
116 "commandStack.shape.move.postExecute"
117 "commandStack.elements.move.preExecute"
118 "commandStack.connection.create.postExecute"
119 "commandStack.connection.reconnect.postExecute"
120 "commandStack.shape.create.executed"
121 "commandStack.shape.create.reverted"
122 "commandStack.shape.create.preExecute"
123 "shape.move.hover"
124 "global-connect.hover"
125 "global-connect.out"
126 "global-connect.end"
127 "global-connect.cleanup"
128 "connect.start"
129 "commandStack.shape.create.execute"
130 "commandStack.shape.create.revert"
131 "commandStack.shape.create.postExecute"
132 "commandStack.elements.create.preExecute"
133 "commandStack.elements.create.revert"
134 "commandStack.elements.create.postExecute"
135 "commandStack.connection.layout.executed"
136 "commandStack.connection.create.executed"
137 "commandStack.connection.layout.reverted"
138 "commandStack.shape.move.executed"
139 "commandStack.shape.delete.executed"
140 "commandStack.connection.move.executed"
141 "commandStack.connection.delete.executed"
142 "commandStack.shape.move.reverted"
143 "commandStack.shape.delete.reverted"
144 "commandStack.connection.create.reverted"
145 "commandStack.connection.move.reverted"
146 "commandStack.connection.delete.reverted"
147 "commandStack.canvas.updateRoot.executed"
148 "commandStack.canvas.updateRoot.reverted"
149 "commandStack.shape.resize.executed"
150 "commandStack.shape.resize.reverted"
151 "commandStack.connection.reconnect.executed"
152 "commandStack.connection.reconnect.reverted"
153 "commandStack.connection.updateWaypoints.executed"
154 "commandStack.connection.updateWaypoints.reverted"
155 "commandStack.element.updateAttachment.executed"
156 "commandStack.element.updateAttachment.reverted"
157 "commandStack.shape.delete.postExecute"
158 "commandStack.canvas.updateRoot.postExecute"
159 "spaceTool.selection.init"
160 "spaceTool.selection.ended"
161 "spaceTool.selection.canceled"
162 "spaceTool.ended"
163 "spaceTool.canceled"
164 "spaceTool.selection.end"
165 "commandStack.shape.delete.postExecuted"
166 "commandStack.connection.create.preExecuted"
167 "commandStack.shape.replace.preExecuted"
168 "bpmnElement.added"
169 "commandStack.element.updateProperties.postExecute"
170 "commandStack或者.label.create.postExecute"
171 "commandStack.connection.layout.postExecute"
172 "commandStack.connection.updateWaypoints.postExecute"
173 "commandStack.shape.replace.postExecute"
174 "commandStack.shape.resize.postExecute"
175 "shape.move.rejected"
176 "create.rejected"
177 "elements.paste.rejected"
178 "commandStack.shape.delete.preExecute"
179 "commandStack.connection.reconnect.preExecute"
180 "commandStack.element.updateProperties.postExecuted"
181 "commandStack.shape.replace.postExecuted"
182 "commandStack.shape.toggleCollapse.executed"
183 "commandStack.shape.toggleCollapse.reverted"
184 "spaceTool.getMinDimensions"
185 "commandStack.connection.delete.preExecute"
186 "commandStack.canvas.updateRoot.preExecute"
187 "commandStack.spaceTool.preExecute"
188 "commandStack.lane.add.preExecute"
189 "commandStack.lane.resize.preExecute"
190 "commandStack.lane.split.preExecute"
191 "commandStack.elements.delete.preExecute"
192 "commandStack.shape.move.preExecute"
193 "commandStack.spaceTool.postExecuted"
194 "commandStack.lane.add.postExecuted"
195 "commandStack.lane.resize.postExecuted"
196 "commandStack.lane.split.postExecuted"
197 "commandStack.elements.delete.postExecuted"
198 "commandStack.shape.move.postExecuted"
199 "saveXML.start"
200 "commandStack.connection.create.preExecute"
201 "commandStack.connection.move.preExecute"
202 "shape.move.out"
203 "shape.move.cleanup"
204 "commandStack.elements.move.preExecuted"
205 "commandStack.shape.delete.execute"
206 "commandStack.shape.delete.revert"
207 "spaceTool.selection.start"
208 "spaceTool.selection.move"
209 "spaceTool.selection.cleanup"
210 "spaceTool.cleanup"
211 "lasso.selection.init"
212 "lasso.selection.ended"
213 "lasso.selection.canceled"
214 "lasso.ended"
215 "lasso.canceled"
216 "lasso.selection.end"
217 "lasso.end"
218 "lasso.start"
219 "lasso.move"
220 "lasso.cleanup"
221 "hand.init"
222 "hand.ended"
223 "hand.canceled"
224 "hand.move.ended"
225 "hand.move.canceled"
226 "hand.end"
227 "hand.move.move"
228 "hand.move.end"
229 "global-connect.init"
230 "global-connect.ended"
231 "global-connect.canceled"
232 "global-connect.drag.ended"
233 "global-connect.drag.canceled"
234 "palette.getProviders"
235 "propertiesPanel.isEntryVisible"
236 "propertiesPanel.isPropertyEditable"
237 "root.added"
238 "propertiesPanel.changed"
239 "propertiesPanel.resized"
240 "elementTemplates.changed"
241 "canvas.resized"
242 "import.parse.complete" 讀取模型(xml)完成
243 "commandStack.changed" 發生任意可撤銷/恢復操做時觸發,可用來實時更新xml

四. Moddles

1. ElementFactory Diagram元素工廠

用於建立各類Diagram(djs.model)元素,並賦予各類屬性。

使用方式:

const ElementFactory = this.bpmnModeler.get("ElementFactory")

方法與返回值:

/**
 * 根據傳入參數建立新的元素
 * type:"root" | "label" | "connection" | "shape"
 * attrs?: object
 */
ElementFactory.create(type, attrs);

衍生方法:

根據create方法傳入的不一樣type,衍生了四種建立圖形元素的方法。

// attrs 非必傳參數
ElementFactory.createRoot(attrs);
ElementFactory.createLabel(attrs);
ElementFactory.createConnection(attrs);
ElementFactory.createShape(attrs);

Bpmn.js補充方法:

因爲 diagram.js 默認只配置了 Shape, Connection, Root, Label 四種元素,不足以支撐整個流程編輯器須要的元素類型。因此Bpmn.js在原來的基礎上增長了其餘方法來定義別的流程元素節點。

// 建立bpmn對應的模型元素
// elementType: string
// attrs?: 自定義屬性
ElementFactory.createBpmnElement(elementType, attrs)

// 建立參與者
// attrs?: object 自定義屬性
ElementFactory.createParticipantShape(attrs)

2. ElementRegistry 圖形註冊表

用於追蹤全部元素。注入了EventBus事件總線。

使用方式:

const ElementRegistry = this.bpmnModeler.get("ElementRegistry")

方法與返回值:

/**
 * 插入新的註冊表
 * @param element:Shape | Connection
 * @param gfx: SVGElement
 * @param secondaryGfx?: SVGElement
 */
ElementRegistry.add(element, gfx, secondaryGfx);

// 移除元素
ElementRegistry.remove(element)

// 更新元素模型的id,同時觸發事件'element.updateId'
ElementRegistry.updateId(element, newId)

// 獲取對應id的元素模型
ElementRegistry.get(id)

// 根據傳入的過濾方法返回符合條件的元素模型數組
ElementRegistry.filter(fn(element, gfx))

// 根據傳入的過濾方法返回符合條件的第一個元素模型
ElementRegistry.find(fn(element, gfx))

// 返回全部已渲染的元素模型
ElementRegistry.getAll()

// 遍歷全部已渲染元素模型,執行傳入方法
ElementRegistry.forEach(fn(element, gfx))

/**
 * 返回對應的SVGElement
 * @param filter:string | Model id或者元素模型
 * @param secondary?: boolean = false 是否返回輔助鏈接的元素
 */
ElementRegistry.getGraphics(filter, secondary)

3. GraphicsFactory 圖形元素工廠

用於建立可顯示的圖形元素。注入了EventBus事件總線與ElementRegistry註冊表。

該類型幾乎不直接使用

使用方式:

const GraphicsFactory = this.bpmnModeler.get("GraphicsFactory")

方法與返回值:

/**
 * 返回建立後的SVGElement
 * @param type:"shape" | "connection" 元素類型
 * @param element?: SVGElement
 * @param parentIndex?: number 位置
 */
GraphicsFactory.create(type, element, parentIndex)

// 繪製節點,觸發"render.shape"
GraphicsFactory.drawShape(visual, element)

// 獲取元素的尺寸等,觸發"render.getShapePath"
GraphicsFactory.getShapePath(element)

// 繪製連線,觸發"render.connection"
GraphicsFactory.drawConnection(visual, element)

// 獲取連線的尺寸等,觸發"render.getConnectionPath"
GraphicsFactory.getConnectionPath(waypoints)

// 更新元素顯示效果(element.type只容許"shape"或者"connaction")
GraphicsFactory.update(element)

GraphicsFactory.remove(element)

4. Canvas 畫布

核心模塊之一,處理全部的元素繪製與顯示。注入了"canvas.config", "EventBus", "GraphicsFactory", "ElementRegistry"。

使用方式:

const Canvas = this.bpmnModeler.get("Canvas")

內部方法:

/**
 * 畫布初始化,根據config配置爲svg元素建立一個div class="djs-container"的父容器。並掛載到制定的dom節點上
 * 並在這個div節點下建立一個svg元素,掛載後面全部節點
 * 以後觸發"diagram.init"與"canvas.init"
 * 同時註冊'shape.added', 'connection.added', 'shape.removed', 'connection.removed', 'elements.changed', 'diagram.destroy', 'diagram.clear'
 * config: object 默認繼承實例化BpmnModeler的配置
 */
Canvas._init(config)

/**
 * 畫布銷燬
 * 觸發"canvas.destroy"
 * 刪除Canvas內部屬性,並移除初始化時聲稱的dom節點
 */
Canvas._destroy()

/**
 * 按類型建立新的元素對象, 同時觸發對應的"[shape | connection].add"和"[shape | connection].added"事件,返回建立的元素對象(衍生的addShape,addConnection方法)
 * @param type: "shape" | "connection" 元素類型
 * @param element: object | djs.model
 * @param parent?: object | djs.model 父元素,默認爲根元素對象
 * @param parentIndex?: number 
 * @return element: object | djs.model
 */
Canvas._addElement(type, element, parent, parentIndex)

/**
 * 移除對應的元素, 同時觸發對應的"[shape | connection].remove"和"[shape | connection].removed"事件,返回被刪除的元素對象(衍生的addShape,addConnection方法)
 * @param type: "shape" | "connection" 元素類型
 * @param element: object | djs.model
 * @param parent?: object | djs.model 父元素,默認爲根元素對象
 * @param parentIndex?: number 
 * @return element: object | djs.model
 */
Canvas._removeElement(element, type)

方法與返回值:

// 返回最上層的SVGElement
Canvas.getDefaultLayer()

// 返回用於在其上繪製元素或註釋的圖層(這個不怎麼理解。。。)
Canvas.getLayer(name, index)

// 返回包含畫布的Dom節點
Canvas.getContainer()

/**
 * 將標記更新包element上(基本上是css類),同時觸發"element.marker.update", 無返回值
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 */
canvas.addMarker(element, marker)


/**
 * 移除元素上的標記,同時觸發"element.marker.update", 無返回值
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 */
canvas.removeMarker(element, marker)

/**
 * 檢測元素是否具備某個標記
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 * @return status: boolean
 */
Canvas.hasMarker(element, marker)

/**
 * 切換元素的標記狀態,存在即remove,不存在則add
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 */
Canvas.toggleMarker(element, marker)

/**
 * 返回畫布的根元素
 * @return element: Object|djs.model
 */
Canvas.getRootElement()

/**
 * 設置新的畫布的根元素,返回新的根元素
 * @param element:object | djs.model
 * @param override: boolean 是否要覆蓋之前的根元素
 * @return element: Object|djs.model
 */
Canvas.setRootElement(element, override)

/**
 * 添加新的節點(形狀)圖形元素
 * @param shape: object | djs.model 插入的元素model或者屬性配置對象
 * @param parent?: djs.model 父元素,默認根節點(畫布下第一級SVG | Root)
 * @param parentIndex?: number 
 * @return Element: djs.model
 */
Canvas.addShape(shape, parent, parentIndex)

/**
 * 添加新的連線元素
 * @param Connaction: object | djs.model 插入的元素model或者屬性配置對象
 * @param parent?: djs.model 父元素,默認根節點(畫布下第一級SVG | Root)
 * @param parentIndex?: number 
 * @return Element: djs.model
 */
Canvas.addConnection(Connaction, parent, parentIndex)

/**
 * 移除節點元素, 返回被移除的節點
 * @param shape: string | djs.model 節點id或者model
 * @return element: djs.model
 */
Canvas.removeShape(shape)

/**
 * 移除連線元素, 返回被移除的對象
 * @param shape: string | djs.model 節點id或者model
 * @return element: djs.model
 */
Canvas.removeConnaction(connection)

/**
 * 查詢圖形元素的SVGElement,即 ElementRegistry.getGraphics()方法。
 * @param shape: string | djs.model 節點id或者model
 * @param secondary?: boolean 
 * @return element: SVGElement
 */
Canvas.getGraphics(element, secondary)

/**
 * 獲取或者設置新的畫布的視圖框。該方法的getter可能會返回一個緩存中的viewbox(若是當前時刻視圖正在發生改變)
 * 若是要強制從新計算,請先執行Canvas.viewbox(false)
 * @param box: Box 新的視圖框配置
 * @param box.x: number = 0 視圖框可見的畫布區域在x軸座標(原點左上角)
 * @param box.y: number = 0 視圖框可見的畫布區域在y軸座標(原點左上角)
 * @param box.width: number 視圖框可見寬度
 * @param box.height: number 視圖框可見高度
 * @return box 當前視圖區域
 */
Canvas.viewbox(box)

/**
 * 具備滾動條時調整滾動位置
 * @param delta:Delta 新的滾動位置
 * @param delta.dx:number x軸方向的位移大小
 * @param delta.dy:number y軸方向的位移大小
 * @return
 */
Canvas.scroll(delta)

/**
 * 設置新的縮放比例或者中心位置,返回當前的縮放比例
 * @param newScale?: number 新的縮放比例
 * @param center?: Point | "auto" | null
 * @param center.x: number
 * @param center.y: number
 * @return scale: number
 */
Canvas.zoom(newScale, center)

// 主動觸發"canvas.resized"事件
Canvas.resized()

// 返回畫布元素的大小
Canvas.getSize()

// 返回畫布的絕對邊界
// @return BBox {
//         x: x;
//         y: y;
//         width: width;
//         height: height;
// }
Canvas.getAbsoluteBBox()

5. EventBus 事件總線

核心模塊之一,通用事件總線, 該組件用於跨圖實例進行通訊。 圖的其餘部分可使用它來偵聽和廣播事件。

使用方式:

const EventBus = this.bpmnModeler.get("eventBus");

核心方法:

/**
 * 註冊事件監聽器
 * @param events: string | string[] 事件名稱(s)
 * @param priority?: number 優先級,默認1000
 * @param callback: Function 回調函數
 * @param that?: object 上下文中的this,會將其傳遞給callback
 */
EventBus.on(events, priority, callback, that)
 
/**
 * 註冊只執行一次的事件監聽器
 * @param events: string | string[] 事件名稱(s)
 * @param priority?: number 優先級,默認1000
 * @param callback: Function 回調函數
 * @param that?: object 上下文中的this,會將其傳遞給callback
 */
EventBus.once(events, priority, callback, that)
 
/**
 * 關閉、刪除事件監聽器
 * @param events
 * @param callback
 */
EventBus.off(events, callback)
 
/**
 * 建立一個可讓EventBus識別的事件,並返回這個事件
 * @param data: object
 * @return event: object
 */
EventBus.createEvent(data)

/**
 * 主動觸發事件
 * @param type: string | object 事件名稱/嵌套事件名稱的對象({type: string})
 * @param data: any 傳遞給回調函數的參數 
 * @return status: boolean | any 事件返回值(若是指定);若是偵聽器阻止了默認操做,則返回false
 */
EventBus.fire(type, data)

6. InternalEvent 事件

指經過事件總線發出來的事件實例。

/**
 * A event that is emitted via the event bus.
 */
function InternalEvent() { }

// 阻止事件傳播給其餘接收者
InternalEvent.prototype.stopPropagation = function() {
  this.cancelBubble = true;
};

// 阻止事件的默認結果
InternalEvent.prototype.preventDefault = function() {
  this.defaultPrevented = true;
};

InternalEvent.prototype.init = function(data) {
  assign(this, data || {});
};

事件能夠結合事件總線對事件監聽器作自定義處理。

好比:

EventBus.on("foo", function(event) {
    console.log(event.type) // "foo"
    event.stopPropagation(); // 中止事件繼續傳播
    event.preventDefault(); // 阻止事件原來的返回值,返回false
})

// 傳入自定義信息
const payload = { fooPayload: "foo" }
EventBus.on("foo", function(event, payload) {
    console.log(payload) // { fooPayload: "foo" }
})
相關文章
相關標籤/搜索