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
系列相关推荐