Bpmn.js 中文文档 之 Overlays
前言
在之前的文章 Bpmn.js 进阶指南之Lint流程校验(四)自定义检验 中我大概提了一下 Bpmn.js 的规则校验模块在显示错误/警告信息的时候,是依赖了 Overlays 模块来显示的,并且说过后面会单独讲述一下这个模块;加上很久很久之前写过了 Bpmn.js 的中文文档(一)和(二),后面就断更了,也算是留下了一个大坑。这次就借更文的机会为每个模块的功能和 API 进行一个说明吧。
🚀作者也为Bpmn.js写了一些实例项目和types声明,有兴趣的同学可以查看这两个地址:bpmn-process-designer、vite-vue-bpmn-process
BpmnOverlays 功能与定义
该模块位于 Bpmn.js 的 底层项目 Diagram.js 中,目录为 diagram-js/lib/features/overlays/Overlays.js。主要功能就是 提供给用户添加 dom 结构的覆盖物到流程元素上,并且在流程图缩放、移动等操作时调整定位。
该模块依赖 EventBus、Canvas、ElementRegistry 三个模块,并且也 接收 config 配置。
其中 config 配置可以在 new Modeler() 时添加一个 key 为 overlays 的对象属性 来设置,该对象接收 show 和 scale 两个参数。
其构造函数定义如下:
type OverlaysConfig = {
show?: {
minZoom?: number
maxZoom?: number
}
scale?: boolean & {
min?: number
max?: number
}
}
export default class Overlays extends ModuleConstructor {
constructor(config: OverlaysConfig | undefined, eventBus: EventBus, canvas: Canvas, elementRegistry: ElementRegistry)
}
覆盖物的显示
那么在我们添加一个覆盖物后页面会变成什么样呢?
以之前 BpmnLint 的校验信息为例,假设我们的流程校验失败显示错误信息时,整个编辑区域的 dom 结构如下:
此时 最外层的 div.bjs-container 和 div.djs-container 是由 Bpmn.js 和 Diagram.js 两个生成的编辑器区域,Bpmn.js 在 Diagram.js 的基础上进行了一次包装,添加了一个项目 Logo。
内部的 svg 元素,则是我们 流程相关的元素的根节点,所有流程元素绑定的 svg 标签都在内部。
而 div.djs-overlays 就是我们的 所有覆盖物显示的根节点了,内部又 按照不同的流程节点元素进行了分组,每个流程节点元素下又按照 “type 类型” 进行了二次分组,在里面才是真实的、我们添加的自定义覆盖物元素内容。
可用方法
在之前的文章中,有提到过 Bpmn.js 内部的各个模块都是通过 Injector 依赖注入 来实现互相引用的,在生成的 Modeler 实例上有一个 get 方法,可以 通过模块名获取模块实例。
所以我们在使用时可以通过这种方式获取到 overlays 实例,在调用其提供的方法。
const modeler = new Modeler({})
const overlays = modeler.get('overlays')
// 后面就可以执行相关的方法了
overlays.xxx()
那么 BpmnOverlays 提供了哪些方法呢?
1. add 覆盖物添加方法
方法定义:
class Overlays {
add(element: Base, type: string | Overlay, overlay?: Overlay): string
}
这写方法都涉及到一些前置参数定义,这里统一说明:
export type Search = { id?: string element?: Base | string type?: string } export type Overlay = { html: string | HTMLElement show?: { minZoom?: number maxZoom?: number } position?: { left?: number top?: number bottom?: number right?: number } scale?: boolean & { min?: number max?: number } } export type Container = { html: Element element: Base overlays: Overlay[] }
其中 Base 是 Bpmn.js 中的 元素实例基础类
add 方法作为 添加覆盖物元素到目标流程元素 上的方法,接收三个参数,其中第二个参数为可选参数:
- element:需要添加覆盖物元素的目标流程元素
- type:用来定义这个覆盖物的类型,如果传递改参数,会 将所有 type 一致的覆盖物元素进行分组
- overlay:具体的覆盖物配置,必传参数为 覆盖物 html 字符串,其他的 show 用来表示最大、最小可见缩放范围,scale 表示覆盖物跟随流程图缩放时的最大、最小缩放倍数
在 add 执行成功后会返回一个该覆盖物对应的 id 字符串
例如 bpmnLint 中添加错误信息时,就是通过这个方法添加的:
var $html = minDom.domify(
'<div class="bjsl-overlay bjsl-issues-' + menuPosition + '"></div>'
);
// ... 一系列错误信息的组合操作
this._overlays.add(element, 'linting', {
position: position,
html: $html,
scale: {
min: .9
}
});
this._overlays 就是 BpmnOverlays 模块的实例,只是在校验模块的内部声明了一个变量来代理。
2. remove 覆盖物移除方法
有添加自然也有移除,在不需要覆盖物的时候就可以通过调用 remove 来移除掉某个覆盖物元素。
方法定义:
class Overlays {
remove(filter: string | Search): void
}
这个方法的效果就很简单啦,就是 按照参数要求移除掉对应的覆盖物元素。
如果参数是一个字符串时,则默认 查找并移除覆盖物 id 等于该字符串的覆盖物,否则就一一匹配并移除。
3. get 覆盖物查找
这个方法接收的参数与 remove 一致,因为 remove 就是通过这个方法来查找要移除的覆盖物元素的啦。
返回值就是一个由覆盖物(types:Overlay)组成的数组,没有查找到则是一个空数组。
class Overlays {
get(search: Search): Overlay | Overlay[] | null
}
4. show 显示/hide 隐藏
这两个方法就很好理解了,就是单纯的字面意思:显示或隐藏所有的覆盖物元素,注意,是所有的。
class Overlays {
show(): void
hide(): void
}
这个方法是处理的最外层的 div.djs-overlays 的 display 属性,类似 Vue 的 v-show,所以需要注意内部某个元素的显示状态。
5. clear 清空覆盖物
这个方法会清除掉最外层的 div.djs-overlays 的 所有子元素,所以使用时也需要注意。
class Overlays {
clear(): void
}
同样的,这个方法也不接收参数,也没有返回值。
完整定义
export default class Overlays extends ModuleConstructor {
constructor(config: any, eventBus: EventBus, canvas: Canvas, elementRegistry: ElementRegistry)
_eventBus: EventBus
_canvas: Canvas
_elementRegistry: ElementRegistry
_overlayDefaults: Overlay
_overlays: Record<string, Overlay | Overlay[]>
_overlayContainers: Container[]
_overlayRoot: Element
_ids: IdGenerator
get(search: Search): Overlay | Overlay[] | null
add(element: Base, type: string, overlay: Overlay): string
remove(filter: string | Object): void
show(): void
hide(): void
clear(): void
_updateOverlayContainer(container: Container): void
_updateOverlay(overlay: Overlay): void
_createOverlayContainer(element: Base): Container
_updateRoot(viewbox: Viewbox): void
_getOverlayContainer(element: Base, raw?: boolean): Container
_addOverlay(overlay: Overlay): void
_updateOverlayVisibilty(overlay: Overlay, viewbox: Viewbox): void
_updateOverlayScale(overlay: Overlay, viewbox: Viewbox): void
_updateOverlaysVisibilty(viewbox: Viewbox): void
}
本身这个模块除了上面暴露的六个基础方法之外,还有一系列的 私有方法(当然也只是命名上的私有,还是可以使用的),用来拆分六个基础方法之中的一些处理逻辑。
这里这些私有方法和属性的定义就留给大家去研究啦。
本身在项目中 Bpmn.js 也很少使用其他模块的私有方法,也是值得我们学习的一点吧。做好对业务逻辑的拆分,也更加容易理解和修改原有代码。