Bpmn.js 中文文檔(一)
由于工作需要(其實不是很需要),在公司項目的基礎上開源了一個基于 bpmn-js + Vue 2.x + ElementUI 的一個流程編輯器 Bpmn Process Designer, 預覽位址 MiyueFE blog, 歡迎 fork 和 star。
一. 引入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模組化器的時候需的參數。
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
類繼承了多個基礎類。
Modeler
-> BaseModeler
-> BaseViewer
-> Diagram
-> Object
Bpmn.js提供的預設擴充包名稱,可以在
this.bpmnModeler.proto._modules
内找到,一共開放了32個擴充包。擴充包名稱可以在
this.bpmnModeler.injector._providers
内,包名即鍵名。
需要調用這些擴充包時,可以使用如下方式:
const xxxModule = this.bpmnModeler.get("xxx"); // xxx代表擴充包名稱
Modeler執行個體化之後可直接調用的方法:
/**
* 傳回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右側元素屬性編輯欄
。
1. palette 與 contentPad
這兩個元件在執行個體化模組化器的時候已經渲染到了頁面上,隻需要引入對應的樣式檔案即可。
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
使用這個元件需要在執行個體化模組化器時修改配置項,并引入對應樣式檔案
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或者碼雲上找到很多大佬的翻譯檔案,将翻譯檔案下載下傳下載下傳儲存到本地。
// 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參數 |
---|---|---|---|
“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)元素,并賦予各種屬性。
使用方式:
方法與傳回值:
/**
* 根據傳入參數建立新的元素
* 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事件總線。
使用方式:
方法與傳回值:
/**
* 插入新的系統資料庫
* @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系統資料庫。
該類型幾乎不直接使用
使用方式:
方法與傳回值:
/**
* 傳回建立後的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" }
})
本文首發于“掘金”
作者:MiyueFE
連結:https://juejin.cn/post/6900793894263488519
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。