【bpmn.js 使用总结】三、自定义工具栏 Palette
自定义 Palette[了解 BPMN 内部】后,对一些模块以及它们之间的配合应该有了一定的概念,下面开始动手尝试修改一下 palette 工具栏案例代码在这里取:customPalette开始你可以实现通过配置生成工具栏自定义工具栏样式、布局可指定工具栏容器为了理解更简单自定义工具栏样式、布局 (非必须,后续实现)可指定工具栏容器(非必须,后续实现)注意:标记 ???? 的地方为重点1. 创建相
自定义 Palette
[了解 BPMN 内部】后,对一些模块以及它们之间的配合应该有了一定的概念,下面开始动手尝试修改一下 palette
工具栏
案例代码在这里取:
开始
你可以实现
- 通过配置生成工具栏
- 自定义工具栏样式、布局
- 可指定工具栏容器
为了理解更简单
- 自定义工具栏样式、布局 (非必须,后续实现)
- 可指定工具栏容器(非必须,后续实现)
注意:标记 🎯 的地方为重点
1. 创建相关文件
建立自定义工具栏的相关文件,结构如下
| -- palette
|-- CustomPaletteProvider.js
|-- CustomPalette.js
|-- index.js
PaletteProvider 顾名思义 ”调色板提供程序“
,也就是将工具栏的数据告诉 Palette
,由 Palette
构造工具栏。
所以我们需要先将代码准备好,然后去修改它:
- 前往 bpmn-js 将源码 PaletteProvider.js 拷贝至 CustomPaletteProvider.js
- 前往 diagram-js 将源码 Palette.js 拷贝至 CustomPalette.js
- 参考
PaletteProvider.js
和Palette.js
对应的index.js
,将刚刚创建的index.js
,修改成如下
import customPalette from './CustomPalette'
import PaletteProvider from './CustomPaletteProvider'
// 除了引进的模块的名字可以修改,其他的不建议修改,会报错
export default {
__depends__: [
{
__init__: ['customPalette'],
customPalette: ['type', customPalette]
}
], // 依赖于 customPalette 这个模块
__init__: ['customPaletteProvider'], // 调用 customPaletteProvider 来初始化
customPaletteProvider: ['type', PaletteProvider]
}
到此三个文件已经准备就绪了,下面我们来引用它。
2. 引用
引入刚刚创建的文件
import customPalette from './palette'
export default {
// ...
init() {
this.bpmnModeler = new BpmnModeler({
additionalModules: [customPalette]
})
// ...
}
}
到此,当前页面应该是正常显示的,因为我们只是将文件拷贝出来,修改引用,方便后续的修改。
3. 修改工具栏构造者 CustomPalette
修改 CustomPalette.js
文件
首先老规则,修改注入需要用的数据
Palette.$inject = [
'eventBus',
'canvas',
// ---------- 自定义区域 ------------
'elementFactory',
'create',
'config.paletteContainer',
'config.paletteEntries'
// ---------- 自定义区域 ------------
]
默认只注入了两个,其余根据需要来增加。
下面将注入的数据赋值
function Palette(
eventBus,
canvas,
elementFactory,
create,
paletteContainer,
paletteEntries
) {
this._eventBus = eventBus
this._canvas = canvas
// 新增赋值
this._entries = paletteEntries // 传入的工具栏数据
this._paletteContainer = paletteContainer // 传入的工具栏容器
this._elementFactory = elementFactory
this._create = create
// ...
}
然后就可以在这个函数中数据注入的数据了,
注意注入顺序和函数参数的顺序要一致哦~
到此,一个数据以及布局已经准备完毕,接下来该实现它的拖动或者点击生成元素
的功能了
Palette.prototype.trigger = function(action, event, autoActivate) {
var entries = this._entries,
entry,
handler,
originalEvent,
button = event.delegateTarget || event.target
// ---------- 自定义区域 ------------
// 创建元素的方法需要这两个构造器
var elementFactory = this._elementFactory,
create = this._create
// ---------- 自定义区域 ------------
handler = entry.action
originalEvent = event.originalEvent || event
// simple action (via callback function)
if (isFunction(handler)) {
if (action === 'click') {
handler(originalEvent, autoActivate, elementFactory, create)
}
} else {
// ---------- 自定义区域 ------------
if (handler[action]) {
// 在原来 2 个参数的基础上,新增 2 个参数 elementFactory, create
handler[action](originalEvent, autoActivate, elementFactory, create) // 🎯 这里便是回调 action.dragstart 或者click 或者 其他事件
}
// ---------- 自定义区域 ------------
}
event.preventDefault()
}
在 init
的时候绑定了两个事件,当我们点击或在拖动工具栏的时候触发,从而可以生成元素。
CustomPalette.js
至此基本修改完成了。
4. 修改数据的提供者 PaletteProvider
现在开始修改 PaletteProvider.js
文件
修改前,可以先看一下 PaletteProvider.prototype.getPaletteEntries
这个方法
源码是在这个方法中将默认工具栏数据传入给 palette.js
可以学习一下他是如何构造工具栏数据的,后面会用到。
如下代码实现了一条分割线和三个事件
// l
'global-connect-tool': {
group: 'tools',
className: 'bpmn-icon-connection-multi',
title: translate('Activate the global connect tool'),
action: {
click: function (event) {
globalConnect.toggle(event)
}
}
},
// 2
'tool-separator': {
group: 'tools',
separator: true
},
// 3
'create.start-event': createAction(
'bpmn:StartEvent', 'event', 'bpmn-icon-start-event-none',
translate('Create StartEvent')
),
// 4
'create.intermediate-event': createAction(
'bpmn:IntermediateThrowEvent', 'event', 'bpmn-icon-intermediate-event-none',
translate('Create Intermediate/Boundary Event')
)
因为我们的目的是希望有一个独立的文件来配置工具栏,而不是在源码中,所以我们开始简化这个 getPaletteEntries 如下:
// 注意: 可以通过 config这个对象拿到 实例化 Modeler 的时候的参数
// 所以这里通过注入 congif.paletteEntries 拿到 paletteEntries 的值
// 后续会介绍如何传入
PaletteProvider.$inject = ['config.paletteEntries', 'customPalette']
export default function PaletteProvider(paletteEntries, customPalette) {
this._entries = paletteEntries
customPalette.registerProvider(this)
}
PaletteProvider.prototype.getPaletteEntries = function(element) {
return this._entries // 🎯 返回工具栏数据
}
5. 配置工具栏 paletteEntries
同级目录下新建 config/paletteEntries.js
,
paletteEntries.js
的目的是返回一个包含工具数据的集合(对象或数组)
这里简单创建两个工具元素,开始和结束
export default {
'create.start-event': createAction(
'bpmn:StartEvent',
'event',
'bpmn-icon-start-event-none',
'Create StartEvent'
),
'create.task': createAction(
'bpmn:Task',
'activity',
'bpmn-icon-task',
'Create Task'
)
}
function createAction(type, group, className, title, options) {
// 还记得 CustomPalette.js 吗?便是这里回调 createListener 函数
// if (action === 'click') {
// handler(originalEvent, autoActivate, elementFactory, create)
// }
function createListener(event, autoActivate, elementFactory, create) {
var shape = elementFactory.createShape({ type })
create.start(event, shape)
}
return {
group: group,
className: className,
title: title,
action: {
dragstart: createListener,
click: createListener
}
}
}
然后再做两件事,引入工具栏配置
、去除默认工具栏
export default {
// ...
init() {
// // 去除默认工具栏
const modules = Modeler.prototype._modules
const index = modules.findIndex(it => it.paletteProvider)
modules.splice(index, 1)
this.bpmnModeler = new BpmnModeler({
paletteEntries,
additionalModules: [customPalette]
})
// ...
}
}
效果如下:
6. 修改样式
bpmn:Task
使用了字体图标 bpmn-icon-task
,
下面我们修改它,换成 img。
修改 paletteEntries.js
export default {
'create.task': createAction(
'bpmn:Task',
'activity',
'bpmn-icon-task-custom', // 🙋♂️ 使用图片后,记得修改成自己的类名
'Create Task',
require('./img/task.png') // 📌
)
}
function createAction(type, group, className, title, imageUrl) {
// ...
return {
group: group,
className: className,
title: title,
imageUrl, // 📌
action: {
dragstart: createListener,
click: createListener
}
}
}
最后
一切大功告成,你将拥有一个全新的工具栏。
突然,你发现通过工具栏生成的元素还保持着 最初
的样子。
无需担心,因为我们还没告诉 bpmn
该怎么渲染它
点击了解如何自定义渲染 customRenderer
相关
可能对你有帮助的官方资源:
目录:
更多推荐
所有评论(0)