因爲工做須要(其實不是很須要),在公司項目的基礎上開源了一個基於 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建模器的時候需的參數。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
這兩個組件在實例化建模器的時候已經渲染到了頁面上,只須要引入對應的樣式文件便可。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";
使用這個組件須要在實例化建模器時修改配置項,並引入對應樣式文件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(); } }
在漢化以前,能夠在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] } ] }) } } }
翻譯文件來自碼雲,可是忘記了做者的信息了,若是做者發現請您聯繫我更改或者刪除
添加鍵盤快捷鍵:數組
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 |
用於建立各類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);
因爲 diagram.js
默認只配置了 Shape, Connection, Root, Label
四種元素,不足以支撐整個流程編輯器須要的元素類型。因此Bpmn.js在原來的基礎上增長了其餘方法來定義別的流程元素節點。
// 建立bpmn對應的模型元素 // elementType: string // attrs?: 自定義屬性 ElementFactory.createBpmnElement(elementType, attrs) // 建立參與者 // attrs?: object 自定義屬性 ElementFactory.createParticipantShape(attrs)
用於追蹤全部元素。注入了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)
用於建立可顯示的圖形元素。注入了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)
核心模塊之一,處理全部的元素繪製與顯示。注入了"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()
核心模塊之一,通用事件總線, 該組件用於跨圖實例進行通訊。 圖的其餘部分可使用它來偵聽和廣播事件。
使用方式:
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)
指經過事件總線發出來的事件實例。
/** * 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" } })