likes
comments
collection

Bpmn.js 中文文档 之 Overlays

作者站长头像
站长
· 阅读数 20

前言

在之前的文章 Bpmn.js 进阶指南之Lint流程校验(四)自定义检验 中我大概提了一下 Bpmn.js 的规则校验模块在显示错误/警告信息的时候,是依赖了 Overlays 模块来显示的,并且说过后面会单独讲述一下这个模块;加上很久很久之前写过了 Bpmn.js 的中文文档(一)和(二),后面就断更了,也算是留下了一个大坑。这次就借更文的机会为每个模块的功能和 API 进行一个说明吧。

🚀作者也为Bpmn.js写了一些实例项目和types声明,有兴趣的同学可以查看这两个地址:bpmn-process-designervite-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 结构如下:

Bpmn.js 中文文档 之 Overlays

此时 最外层的 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-overlaysdisplay 属性,类似 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 也很少使用其他模块的私有方法,也是值得我们学习的一点吧。做好对业务逻辑的拆分,也更加容易理解和修改原有代码。