Q: bpmn.js是什麼? 🤔️javascript
bpmn.js是一個BPMN2.0渲染工具包和web建模器, 使得畫流程圖的功能在前端來完成.前端
Q: 我爲何要寫該系列的教材? 🤔️vue
由於公司業務的須要於是要在項目中使用到bpmn.js
,可是因爲bpmn.js
的開發者是國外友人, 所以國內對這方面的教材不多, 也沒有詳細的文檔. 因此不少使用方式不少坑都得本身去找.在將其琢磨完以後, 決定寫一系列關於它的教材來幫助更多bpmn.js
的使用者或者是期於找到一種好的繪製流程圖的開發者. 同時也是本身對其的一種鞏固.java
因爲是系列的文章, 因此更新的可能會比較頻繁, 您要是無心間刷到了且不是您所須要的還請諒解😊.git
不求贊👍不求心❤️. 只但願能對你有一點小小的幫助.github
上一章節咱們介紹了利用bpmn.js
與後臺進行交互, 要是對bpmn.js
不瞭解的小夥請移步:web
這一章節要講解是關於bpmn.js
的一些事件, 經過學習此章節你能夠學習到:dom
不少時候你指望的是在用戶在進行不一樣操做的時候可以監聽到他操做的是什麼, 從而作想要作的事情.svg
是進行了shape
的新增仍是進行了線的新增.
好比以下的一些監聽事件:
shape
以後觸發;shape
以後觸發;shape
以後觸發;繼續在項目案例bpmn-vue-basic的基礎上建立一個event.vue
文件:
並在success()
函數中添加上監聽事件的函數:
// event.vue
<script>
...
success () {
this.addModelerListener()
},
// 監聽 modeler
addModelerListener() {
const bpmnjs = this.bpmnModeler
const that = this
// 這裏我是用了一個forEach給modeler上添加要綁定的事件
const events = ['shape.added', 'shape.move.end', 'shape.removed', 'connect.end', 'connect.move']
events.forEach(function(event) {
that.bpmnModeler.on(event, e => {
console.log(event, e)
var elementRegistry = bpmnjs.get('elementRegistry')
var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
console.log(shape)
})
})
},
複製代碼
如圖所示, 在這裏你就能夠獲取到相關節點的全部信息了:
案例Git地址: LinDaiDai-bpmn.js案例event.vue
其實具體有哪些事件我在官網上都沒有找到說明, 以上只是我在查找到bpmn.io/diagram.js/…文件以後, 取的一些我項目裏有用到的事件.
上面介紹的是監聽modeler
並綁定事件, 可能你也須要監聽用戶點擊圖形上的element
或者監聽某個element
改變:
繼續在success()
上添加監聽事件:
// event.vue
<script>
...
success () {
...
this.addEventBusListener()
},
addEventBusListener () {
let that = this
const eventBus = this.bpmnModeler.get('eventBus') // 須要使用eventBus
const eventTypes = ['element.click', 'element.changed'] // 須要監聽的事件集合
eventTypes.forEach(function(eventType) {
eventBus.on(eventType, function(e) {
console.log(e)
})
})
}
</script>
複製代碼
配置好addEventBusListener()
函數後, 在進行元素的點擊、新增、移動、刪除的時候都能監聽到了.
可是有一點很很差, 你在點擊「畫布」的時候, 也就是根元素也可能會觸發此事件, 咱們通常都不但願此時會觸發, 所以咱們能夠在on
回調中添加一些判斷, 來避免掉不須要的狀況:
eventBus.on(eventType, function(e) {
if (!e || e.element.type == 'bpmn:Process') return // 這裏個人根元素是bpmn:Process
console.log(e)
})
複製代碼
此時咱們能夠把監聽到返回的節點信息打印出來看看:
如上圖, 它會打印出該節點的Shape
信息和DOM
信息等, 但咱們可能只關注於Shape
信息(也就是該節點的id、type
等等信息), 此時咱們可使用elementRegistry
來獲取Shape
信息:
eventBus.on(eventType, function(e) {
if (!e || e.element.type == 'bpmn:Process') return // 這裏個人根元素是bpmn:Process
console.log(e)
var elementRegistry = this.bpmnModeler.get('elementRegistry')
var shape = elementRegistry.get(e.element.id) // 傳遞id進去
console.log(shape) // {Shape}
console.log(e.element) // {Shape}
console.log(JSON.stringify(shape)===JSON.stringify(e.element)) // true
})
複製代碼
或者你也能夠直接就用e.element
獲取到Shape
的信息, 我比較了一下它們兩是同樣的. 可是官方是推薦使用elementRegistry
的方式.
上面咱們已經介紹了modeler
和element
的監聽綁定方式, 在事件應用中, 你更多的須要知道用戶要進行什麼操做, 好寫對應的業務邏輯.
這裏我就以我工做中要用到的場景爲案例進行講解.
// event.vue
...
success () {
this.addModelerListener()
this.addEventBusListener()
},
// 添加綁定事件
addBpmnListener () {
const that = this
// 獲取a標籤dom節點
const downloadLink = this.$refs.saveDiagram
const downloadSvgLink = this.$refs.saveSvg
// 給圖綁定事件,當圖有發生改變就會觸發這個事件
this.bpmnModeler.on('commandStack.changed', function () {
that.saveSVG(function(err, svg) {
that.setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg)
})
that.saveDiagram(function(err, xml) {
that.setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml)
})
})
},
addModelerListener() {
// 監聽 modeler
const bpmnjs = this.bpmnModeler
const that = this
// 'shape.removed', 'connect.end', 'connect.move'
const events = ['shape.added', 'shape.move.end', 'shape.removed']
events.forEach(function(event) {
that.bpmnModeler.on(event, e => {
var elementRegistry = bpmnjs.get('elementRegistry')
var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
// console.log(shape)
if (event === 'shape.added') {
console.log('新增了shape')
} else if (event === 'shape.move.end') {
console.log('移動了shape')
} else if (event === 'shape.removed') {
console.log('刪除了shape')
}
})
})
},
addEventBusListener() {
// 監聽 element
let that = this
const eventBus = this.bpmnModeler.get('eventBus')
const eventTypes = ['element.click', 'element.changed']
eventTypes.forEach(function(eventType) {
eventBus.on(eventType, function(e) {
if (!e || e.element.type == 'bpmn:Process') return
if (eventType === 'element.changed') {
that.elementChanged(eventType, e)
} else if (eventType === 'element.click') {
console.log('點擊了element')
}
})
})
},
elementChanged(eventType, e) {
var shape = this.getShape(e.element.id)
if (!shape) {
// 如果shape爲null則表示刪除, 不管是shape仍是connect刪除都調用此處
console.log('無效的shape')
// 因爲上面已經用 shape.removed 檢測了shape的刪除, 所以這裏只判斷是不是線
if (this.isSequenceFlow(shape.type)) {
console.log('刪除了線')
}
}
if (!this.isInvalid(shape.type)) {
if (this.isSequenceFlow(shape.type)) {
console.log('改變了線')
}
}
},
getShape(id) {
var elementRegistry = this.bpmnModeler.get('elementRegistry')
return elementRegistry.get(id)
},
isInvalid (param) { // 判斷是不是無效的值
return param === null || param === undefined || param === ''
},
isSequenceFlow (type) { // 判斷是不是線
return type === 'bpmn:SequenceFlow'
}
複製代碼
案例Git地址: LinDaiDai-bpmn.js案例event.vue
系列相關推薦