Bpmn.js 中文文档(一)_MiyueFE的博客-程序员秘密

技术标签: bpmn  vue  bpmn.js  javascript  

Bpmn.js 中文文档(一)

由于工作需要(其实不是很需要),在公司项目的基础上开源了一个基于 bpmn-js + Vue 2.x + ElementUI 的一个流程编辑器 Bpmn Process Designer, 预览地址 MiyueFE blog, 欢迎 fork 和 star。

一. 引入Bpmn.js并初始化建模器

/* 基于vue2.x, 省略了template模板与部分data */

import BpmnModeler from "bpmn-js/lib/Modeler"

export default {
    
    methods: {
    
        initModeler() {
    
            this.bpmnModeler = new BpmnModeler({
    
                container: document.getElementById("bpmn-container")
            })
        }
    },
    mounted() {
    
        this.initModeler();
    }
}

进入到源文件Modeler.js,可以找到创建Modeler建模器的时候需的参数。

this.bpmnModeler = new BpmnModeler(options: Options);

interface Options {
	container: DomElement; // 渲染容器
	width:string | number;// 查看器宽度
	height: string | number; // 查看器高度
	moddleExtensions: object;// 需要用的扩展包
	modules:<didi.Module>[]; // 自定义且需要覆盖默认扩展包的模块列表
	additionalModules: <didi.Module>[]; // 自定义且与默认扩展包一起使用的模块列表
}

初始化完成之后,在控制台打印this.bpmnModeler,可以发现BpmnModeler类继承了多个基础类。

Modeler
	-> BaseModeler
		-> BaseViewer
			-> Diagram
				-> Object

Bpmn.js提供的默认扩展包名称,可以在this.bpmnModeler.proto._modules内找到,一共开放了32个扩展包。扩展包名称可以在this.bpmnModeler.injector._providers内,包名即键名。

需要调用这些扩展包时,可以使用如下方式:

const xxxModule = this.bpmnModeler.get("xxx"); // xxx代表扩展包名称

Modeler实例化之后可直接调用的方法:

/**
 * 返回name对应的模块实例
 * @param { string } name 模块名
 * @param { boolean } strict 启用严格模式。false:缺少的模块解析为null返回;true:抛出异常
 */
this.bpmnModeler.get(name, strict);

// 创建空白流程图
// 内部调用了importXML方法,读取内部的默认xml字符串
this.bpmnModeler.createDiagram();

// 将图形dom挂载到目标节点
this.bpmnModeler.attachTo(parentNode);

// 清空
this.bpmnModeler.clear()

// 销毁
this.bpmnModeler.destroy()

// 脱离dom
this.bpmnModeler.detach()

// 获取流程定义
this.bpmnModeler.getDefinitions()

// 获取扩展功能模块列表
this.bpmnModeler.getModules()

/**
 * 导入解析的定义并呈现BPMN 2.0图。完成后,查看器将结果报告回给提供的回调函数(错误,警告)
 * @param { ModdleElement<Definitions> } definitions 模块名
 * @param { ModdleElement<BPMNDiagram>|string } [bpmnDiagram] 要呈现的BPMN图或图的ID(如果未提供,将呈现第一个)
 */
this.bpmnModeler.importDefinitions(definitions, bpmnDiagram)

/**
 * 导入xml(字符串形式),返回导入结果
 * 后续会取消传入回调函数的方式
 * 推荐使用async/await或者链式调用
 * @param { string } xml 流程图xml字符串
 * @param { Promise } callback 回调函数,出错时返回{ warnings,err }
 */
this.bpmnModeler.importXML(xml, callback)

// 注销事件监听器
this.bpmnModeler.off(eventName, callback)

// 注册事件监听,同名将删除以前的监听器,privorty可不传,程序会自动替换回调函数
this.bpmnModeler.on(eventName, priority, callback, target)

// em。。。不了解
this.bpmnModeler.open()

// 保存为svg文件,与importXML方法一样,后续会取消传入callback的方式
this.bpmnModeler.saveSVG(callback)

// 保存为xml文件,与importXML方法一样,后续会取消传入callback的方式
this.bpmnModeler.saveXML(callback)
	

二. 基础功能

使用过程中,常用的组件主要包含:palette 左侧元素栏、 contentPad 元素操作块、 propertiesPanel右侧元素属性编辑栏

1. palette 与 contentPad

这两个组件在实例化建模器的时候已经渲染到了页面上,只需要引入对应的样式文件即可。

import "bpmn-js/dist/assets/diagram-js.css";
import "bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
import "bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";

2. propertiesPanel

使用这个组件需要在实例化建模器时修改配置项,并引入对应样式文件

import "bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css"; // 右边工具栏样式

import propertiesPanelModule from "bpmn-js-properties-panel";
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";

export default {
    
    methods: {
    
        initModeler() {
    
            this.bpmnModeler = new BpmnModeler({
    
                container: document.getElementById("bpmn-container"),
                propertiesPanel: {
    
                  parent: "#attrs-panel"
                },
                additionalModules: [ propertiesPanelModule, propertiesProviderModule ]
            })
        }
    },
    mounted() {
    
        this.initModeler();
    }
}

3. 汉化

在汉化之前,可以在github或者码云上找到很多大佬的翻译文件,将翻译文件下载下载保存到本地。

// 1. 创建翻译文件 zh.js(命名随意),导出英文关键字对应的中文翻译
export default {
    
    "Append EndEvent": "追加结束事件",
    "Append Gateway": "追加网关",
    "Append Task": "追加任务",
    "Append Intermediate/Boundary Event": "追加中间抛出事件/边界事件",
    ...
}
    
// 2. 建立翻译模块方法customTranslate.js
import translations from "./zh";

export default function customTranslate(template, replacements) {
    
  replacements = replacements || {
    };

  // Translate
  template = translations[template] || template;

  // Replace
  return template.replace(/{([^}]+)}/g, function(_, key) {
    
    let str = replacements[key];
    if (
      translations[replacements[key]] !== null &&
      translations[replacements[key]] !== "undefined"
    ) {
    
      // eslint-disable-next-line no-mixed-spaces-and-tabs
      str = translations[replacements[key]];
      // eslint-disable-next-line no-mixed-spaces-and-tabs
    }
    return str || "{" + key + "}";
  });
}

// 3. 在实例化建模器时以自定义模块的方式传入参数
import customTranslate from "./pugins/customTranslate";

export default {
    
  methods: {
    
    initModeler() {
    
        this.bpmnModeler = new BpmnModeler({
    
            container: document.getElementById("bpmn-container"),
            additionalModules: [
            	{
     translate: ["value", customTranslate] }
            ]
        })
    }
  }
}

翻译文件来自码云,但是忘记了作者的信息了,如果作者发现请您联系我更改或者删除

4. 其他功能(非自定义的功能模块配置项)

添加键盘快捷键:

this.bpmnModeler = new BpmnModeler({
    
    container: document.getElementById("bpmn-container"),
    keyboard: {
    
    	bindTo: document // 或者window,注意与外部表单的键盘监听事件是否冲突
    }
});

三. 事件

Bpmn.js 提供了EventBus事件总线模块来管理监听事件,并预设了244个事件。

下面的元素对象指包含element元素的对象,其他属性不定(部分事件返回的对象也不包含element)。

“ - ” 短横线表示暂时没有找到何时触发该事件

以下事件均可使用this.bpmnModeler.on(eventName, callback)或者eventBus.on(eventName, callback)的形式注册。

// 通过事件总线发出的事件
interface InternalEvent {
    
    type: string; // 发生的事件名称,但是很快会被置为undefined
    element: Shape | Connection;
    elements: Element[];
    shape: Shape;
    context: object; // 有点复杂,有兴趣的朋友可以研究
    gfx?: SVGElement;
    svg?: SVGElement;
    viewport?: SVGElement;
    viewbox?: Viewbox;
    pad?: object; // 见 Element.pad
}

interface Element {
    
    element: Shape | Connection;
    gfx?: SVGElement;
    pad?: {
    
        id: string;
        html: DOMElement;
        position: {
     right: number; top: number };
    	scale: {
     max: number; min: number };
    	show: object | null;
    	type: string; // 一般是"context-pad"
    }
}

interface Elements {
    
    elements: Array<Shape | Connection>
}

interface Canvas {
    
    svg?: SVGElement;
    viewport?: SVGElement;
}

interface Viewbox {
    
	viewbox: {
    
        height: number;
        width: number;
        x: number;
        y: number;
        inter: object; // 包含x,y,width,height的一个对象
        outer: object; // 包含x,y,width,height的一个对象
        scale: number; // 当前缩放比例(小数)
	}
}
序号 事件名 说明 callback参数
0 “diagram.destroy” 流程编辑器销毁 event:InternalEvent
1 “render.shape” 调用GraphicsFactory.drawShape时触发,开始渲染形状
2 “render.connection” 调用GraphicsFactory.drawConnection时触发,开始渲染连线
3 “render.getShapePath” 调用GraphicsFactory.getShapePath时触发,开始获取形状路径
4 “render.getConnectionPath” 调用GraphicsFactory.getConnectionPath时触发
5 “diagram.init” 指示画布已准备好在其上进行绘制
6 “shape.added” 已更新到xml内,触发渲染方法,返回值为插入的新元素 event:InternalEvent, element: Element
7 “connection.added” 已更新到xml内,触发渲染方法,返回值为插入的新元素 event:InternalEvent, element: Element
8 “shape.removed” 形状移除完成,返回值为被移除元素 event:InternalEvent, element: Element
9 “connection.removed” 连线移除完成,返回值为被移除元素
10 “elements.changed” 元素发生改变并更改完成 event: InternalEvent, element: Elements
11 “diagram.clear” 流程编辑器元素及画布已清空 event:InternalEvent
12 “canvas.destroy” 画布销毁 event:InternalEvent
13 “canvas.init” 画布初始化完成
14 “shape.changed” 形状属性更新,返回当前元素 event:InternalEvent, element: Element
15 “connection.changed” 连线属性更新,返回当前元素 event:InternalEvent, element: Element
16 “interactionEvents.createHit” shape.added,connection.added之后触发
17 “interactionEvents.updateHit” shape.changed,connection.changed之后触发
18 “shape.remove” 形状被选中移除,返回被移除的元素对象 event:InternalEvent, element: Element
19 “connection.remove” 连线被选中移除 event:InternalEvent, element: Element
20 “element.hover” 鼠标移动到元素上,返回鼠标位置处元素对象 event:InternalEvent, element: Element
21 “element.out” 鼠标移出元素,返回鼠标最近移入的元素对象 event:InternalEvent, element: Element
22 “selection.changed” 选中元素变化时,返回新选中的元素对象 event:InternalEvent, element: Element
23 “create.end” 从palette中新建的元素创建完成(不清楚为什么有两个相同的参数) event:InternalEvent, event:InternalEvent
24 “connect.end” 从palette中或者从选中节点中新建的连线元素创建完成(不清楚为什么有两个相同的参数) event:InternalEvent, event:InternalEvent
25 “shape.move.end” 形状元素移动结束后 event:InternalEvent, element: Element
26 “element.click” 元素单击事件 event:InternalEvent, element: Element
27 “canvas.viewbox.changing” 视图缩放过程中 event:InternalEvent
28 “canvas.viewbox.changed” 视图缩放完成 event:InternalEvent, viewbox: Viewbox
29 “element.changed” 元素发生改变时触发,返回发生改变的元素 event:InternalEvent, element: Element
30 “element.marker.update” 元素标识更新时触发
31 “attach” 画布或者根节点重新挂载时
32 “detach” 画布或者根节点移除挂载时
33 “editorActions.init” 流程编辑模块加载完成
34 “keyboard.keydown” 键盘按键按下
35 “element.mousedown” 鼠标在元素上按下时触发 event:InternalEvent, element: Element
36 “commandStack.connection.start.canExecute” 连线开始时检测是否可以创建连线,点击创建连线的按钮时触发
37 “commandStack.connection.create.canExecute” 连线开始时检测是否可以创建连线,
38 “commandStack.connection.reconnect.canExecute” 检测连线是否可以修改
39 “commandStack.connection.updateWaypoints.canExecute” 检测是否可以更新连线拐点
40 “commandStack.shape.resize.canExecute” 检测形状是否可以更改大小
41 “commandStack.elements.create.canExecute” 检测是否可以创建元素
42 “commandStack.elements.move.canExecute” 检测是否可以移动元素
43 “commandStack.shape.create.canExecute” 检测是否可以创建形状
44 “commandStack.shape.attach.canExecute” 检测元素是否可以挂载到目标上
45 “commandStack.element.copy.canExecute” 检测元素是否可以被复制
46 “shape.move.start” 形状开始移动 event:InternalEvent, element: Element
47 “shape.move.move” 形状移动过程中 event:InternalEvent, element: Element
48 “elements.delete” 元素被删除,返回被删除的元素 event:InternalEvent, element: Element
49 “tool-manager.update”
50 “i18n.changed”
51 “drag.move” 元素拖拽过程中 event:InternalEvent, event:InternalEvent
52 “contextPad.create” 当contextPad出现的时候触发 event:InternalEvent, element: Element
53 “palette.create” 左侧palette开始创建
54 “autoPlace.end” 自动对齐结束
55 “autoPlace” 触发自动对齐方法时
56 “drag.start” 元素拖拽开始 event:InternalEvent, event:InternalEvent
57 “drag.init” 点击了元素即将进行拖拽(包括点击palette和画布内的元素) event:InternalEvent, event:InternalEvent
58 “drag.cleanup” 元素拖拽结束 event:InternalEvent, event:InternalEvent
59 “commandStack.shape.create.postExecuted” 当创建形节点的时候触发 event:InternalEvent, event:InternalEvent
60 “commandStack.elements.move.postExecuted” 当元素移动的时候触发 event:InternalEvent, event:InternalEvent
61 “commandStack.shape.toggleCollapse.postExecuted” 当可折叠的节点展开/折叠的时候触发 event:InternalEvent, event:InternalEvent
62 “commandStack.shape.resize.postExecuted” 当节点大小发生改变的时候触发 event:InternalEvent, event:InternalEvent
63 “commandStack.element.autoResize.canExecute” 当节点大小发生自动调整的时候触发 event:InternalEvent, event:InternalEvent
64 “bendpoint.move.hover” 鼠标点击连线折点并进行移动时触发 event:InternalEvent, event:InternalEvent
65 “bendpoint.move.out” 返回时间不定,可能在拖动时触发,也可能在拖动过程中 event:InternalEvent, event:InternalEvent
66 “bendpoint.move.cleanup” 鼠标点击连线折点时或者移动折点完成 event:InternalEvent, event:InternalEvent
67 “bendpoint.move.end” 鼠标点击连线折点并移动完成 event:InternalEvent, event:InternalEvent
68 “connectionSegment.move.start” 鼠标选中连线进行拖动开始 event:InternalEvent, event:InternalEvent
69 “connectionSegment.move.move” 鼠标选中连线进行拖动过程中 event:InternalEvent, event:InternalEvent
70 “connectionSegment.move.hover” 鼠标选中连线进行拖动开始 event:InternalEvent, event:InternalEvent
71 “connectionSegment.move.out” 鼠标选中连线,按下鼠标时 event:InternalEvent, event:InternalEvent
72 “connectionSegment.move.cleanup” 鼠标选中连线后放开鼠标时 event:InternalEvent, event:InternalEvent
73 “connectionSegment.move.cancel” 选中连线之后取消连接 event:InternalEvent, event:InternalEvent
74 “connectionSegment.move.end” 选中连线并拖拽结束 event:InternalEvent, event:InternalEvent
75 “element.mousemove” 鼠标移除元素后
76 “element.updateId” 更新元素id时触发
77 “bendpoint.move.move” 连线上的拐点被拖拽移动时触发
78 “bendpoint.move.start” 连线上的拐点被拖拽移动开始时触发
79 “bendpoint.move.cancel” 连线上的拐点被点击并取消拖拽
80 “connect.move” 连线被移动时
81 “connect.hover”
82 “connect.out”
83 “connect.cleanup”
84 “create.move”
85 “create.hover”
86 “create.out”
87 “create.cleanup”
88 “create.init”
89 “copyPaste.copyElement”
90 “copyPaste.pasteElements”
91 “moddleCopy.canCopyProperties”
92 “moddleCopy.canCopyProperty”
93 “moddleCopy.canSetCopiedProperty”
94 “copyPaste.pasteElement”
95 “popupMenu.getProviders.bpmn-replace”
96 “contextPad.getProviders”
97 “resize.move”
98 “resize.end”
99 “commandStack.shape.resize.preExecute”
100 “spaceTool.move”
101 “spaceTool.end”
102 “create.start”
103 “commandStack.connection.create.postExecuted”
104 “commandStack.connection.layout.postExecuted”
105 “shape.move.init”
106 “resize.start”
107 “resize.cleanup”
108 “directEditing.activate”
109 “directEditing.resize”
110 “directEditing.complete”
111 “directEditing.cancel”
112 “commandStack.connection.updateWaypoints.postExecuted”
113 “commandStack.label.create.postExecuted”
114 “commandStack.elements.create.postExecuted”
115 “commandStack.shape.append.preExecute”
116 “commandStack.shape.move.postExecute”
117 “commandStack.elements.move.preExecute”
118 “commandStack.connection.create.postExecute”
119 “commandStack.connection.reconnect.postExecute”
120 “commandStack.shape.create.executed”
121 “commandStack.shape.create.reverted”
122 “commandStack.shape.create.preExecute”
123 “shape.move.hover”
124 “global-connect.hover”
125 “global-connect.out”
126 “global-connect.end”
127 “global-connect.cleanup”
128 “connect.start”
129 “commandStack.shape.create.execute”
130 “commandStack.shape.create.revert”
131 “commandStack.shape.create.postExecute”
132 “commandStack.elements.create.preExecute”
133 “commandStack.elements.create.revert”
134 “commandStack.elements.create.postExecute”
135 “commandStack.connection.layout.executed”
136 “commandStack.connection.create.executed”
137 “commandStack.connection.layout.reverted”
138 “commandStack.shape.move.executed”
139 “commandStack.shape.delete.executed”
140 “commandStack.connection.move.executed”
141 “commandStack.connection.delete.executed”
142 “commandStack.shape.move.reverted”
143 “commandStack.shape.delete.reverted”
144 “commandStack.connection.create.reverted”
145 “commandStack.connection.move.reverted”
146 “commandStack.connection.delete.reverted”
147 “commandStack.canvas.updateRoot.executed”
148 “commandStack.canvas.updateRoot.reverted”
149 “commandStack.shape.resize.executed”
150 “commandStack.shape.resize.reverted”
151 “commandStack.connection.reconnect.executed”
152 “commandStack.connection.reconnect.reverted”
153 “commandStack.connection.updateWaypoints.executed”
154 “commandStack.connection.updateWaypoints.reverted”
155 “commandStack.element.updateAttachment.executed”
156 “commandStack.element.updateAttachment.reverted”
157 “commandStack.shape.delete.postExecute”
158 “commandStack.canvas.updateRoot.postExecute”
159 “spaceTool.selection.init”
160 “spaceTool.selection.ended”
161 “spaceTool.selection.canceled”
162 “spaceTool.ended”
163 “spaceTool.canceled”
164 “spaceTool.selection.end”
165 “commandStack.shape.delete.postExecuted”
166 “commandStack.connection.create.preExecuted”
167 “commandStack.shape.replace.preExecuted”
168 “bpmnElement.added”
169 “commandStack.element.updateProperties.postExecute”
170 “commandStack或者.label.create.postExecute”
171 “commandStack.connection.layout.postExecute”
172 “commandStack.connection.updateWaypoints.postExecute”
173 “commandStack.shape.replace.postExecute”
174 “commandStack.shape.resize.postExecute”
175 “shape.move.rejected”
176 “create.rejected”
177 “elements.paste.rejected”
178 “commandStack.shape.delete.preExecute”
179 “commandStack.connection.reconnect.preExecute”
180 “commandStack.element.updateProperties.postExecuted”
181 “commandStack.shape.replace.postExecuted”
182 “commandStack.shape.toggleCollapse.executed”
183 “commandStack.shape.toggleCollapse.reverted”
184 “spaceTool.getMinDimensions”
185 “commandStack.connection.delete.preExecute”
186 “commandStack.canvas.updateRoot.preExecute”
187 “commandStack.spaceTool.preExecute”
188 “commandStack.lane.add.preExecute”
189 “commandStack.lane.resize.preExecute”
190 “commandStack.lane.split.preExecute”
191 “commandStack.elements.delete.preExecute”
192 “commandStack.shape.move.preExecute”
193 “commandStack.spaceTool.postExecuted”
194 “commandStack.lane.add.postExecuted”
195 “commandStack.lane.resize.postExecuted”
196 “commandStack.lane.split.postExecuted”
197 “commandStack.elements.delete.postExecuted”
198 “commandStack.shape.move.postExecuted”
199 “saveXML.start”
200 “commandStack.connection.create.preExecute”
201 “commandStack.connection.move.preExecute”
202 “shape.move.out”
203 “shape.move.cleanup”
204 “commandStack.elements.move.preExecuted”
205 “commandStack.shape.delete.execute”
206 “commandStack.shape.delete.revert”
207 “spaceTool.selection.start”
208 “spaceTool.selection.move”
209 “spaceTool.selection.cleanup”
210 “spaceTool.cleanup”
211 “lasso.selection.init”
212 “lasso.selection.ended”
213 “lasso.selection.canceled”
214 “lasso.ended”
215 “lasso.canceled”
216 “lasso.selection.end”
217 “lasso.end”
218 “lasso.start”
219 “lasso.move”
220 “lasso.cleanup”
221 “hand.init”
222 “hand.ended”
223 “hand.canceled”
224 “hand.move.ended”
225 “hand.move.canceled”
226 “hand.end”
227 “hand.move.move”
228 “hand.move.end”
229 “global-connect.init”
230 “global-connect.ended”
231 “global-connect.canceled”
232 “global-connect.drag.ended”
233 “global-connect.drag.canceled”
234 “palette.getProviders”
235 “propertiesPanel.isEntryVisible”
236 “propertiesPanel.isPropertyEditable”
237 “root.added”
238 “propertiesPanel.changed”
239 “propertiesPanel.resized”
240 “elementTemplates.changed”
241 “canvas.resized”
242 “import.parse.complete” 读取模型(xml)完成
243 “commandStack.changed” 发生任意可撤销/恢复操作时触发,可用来实时更新xml

四. Moddles

1. ElementFactory Diagram元素工厂

用于创建各种Diagram(djs.model)元素,并赋予各种属性。

使用方式:

const ElementFactory = this.bpmnModeler.get("elementFactory")

方法与返回值:

/**
 * 根据传入参数创建新的元素
 * type:"root" | "label" | "connection" | "shape"
 * attrs?: object
 */
ElementFactory.create(type, attrs);

衍生方法:

根据create方法传入的不同type,衍生了四种创建图形元素的方法。

// attrs 非必传参数
ElementFactory.createRoot(attrs);
ElementFactory.createLabel(attrs);
ElementFactory.createConnection(attrs);
ElementFactory.createShape(attrs);

Bpmn.js补充方法:

由于 diagram.js 默认只配置了 Shape, Connection, Root, Label 四种元素,不足以支撑整个流程编辑器需要的元素类型。所以Bpmn.js在原来的基础上增加了其他方法来定义别的流程元素节点。

// 创建bpmn对应的模型元素
// elementType: string
// attrs?: 自定义属性
ElementFactory.createBpmnElement(elementType, attrs)

// 创建参与者
// attrs?: object 自定义属性
ElementFactory.createParticipantShape(attrs)

2. ElementRegistry 图形注册表

用于追踪所有元素。注入了EventBus事件总线。

使用方式:

const ElementRegistry = this.bpmnModeler.get("elementRegistry")

方法与返回值:

/**
 * 插入新的注册表
 * @param element:Shape | Connection
 * @param gfx: SVGElement
 * @param secondaryGfx?: SVGElement
 */
ElementRegistry.add(element, gfx, secondaryGfx);

// 移除元素
ElementRegistry.remove(element)

// 更新元素模型的id,同时触发事件'element.updateId'
ElementRegistry.updateId(element, newId)

// 获取对应id的元素模型
ElementRegistry.get(id)

// 根据传入的过滤方法返回符合条件的元素模型数组
ElementRegistry.filter(fn(element, gfx))

// 根据传入的过滤方法返回符合条件的第一个元素模型
ElementRegistry.find(fn(element, gfx))

// 返回所有已渲染的元素模型
ElementRegistry.getAll()

// 遍历所有已渲染元素模型,执行传入方法
ElementRegistry.forEach(fn(element, gfx))

/**
 * 返回对应的SVGElement
 * @param filter:string | Model id或者元素模型
 * @param secondary?: boolean = false 是否返回辅助连接的元素
 */
ElementRegistry.getGraphics(filter, secondary)

3. GraphicsFactory 图形元素工厂

用于创建可显示的图形元素。注入了EventBus事件总线与ElementRegistry注册表。

该类型几乎不直接使用

使用方式:

const GraphicsFactory = this.bpmnModeler.get("graphicsFactory")

方法与返回值:

/**
 * 返回创建后的SVGElement
 * @param type:"shape" | "connection" 元素类型
 * @param element?: SVGElement
 * @param parentIndex?: number 位置
 */
GraphicsFactory.create(type, element, parentIndex)

// 绘制节点,触发"render.shape"
GraphicsFactory.drawShape(visual, element)

// 获取元素的尺寸等,触发"render.getShapePath"
GraphicsFactory.getShapePath(element)

// 绘制连线,触发"render.connection"
GraphicsFactory.drawConnection(visual, element)

// 获取连线的尺寸等,触发"render.getConnectionPath"
GraphicsFactory.getConnectionPath(waypoints)

// 更新元素显示效果(element.type只允许"shape"或者"connaction")
GraphicsFactory.update(element)

GraphicsFactory.remove(element)

4. Canvas 画布

核心模块之一,处理所有的元素绘制与显示。注入了"canvas.config", “EventBus”, “GraphicsFactory”, “ElementRegistry”。

使用方式:

const Canvas = this.bpmnModeler.get("canvas")

内部方法:

/**
 * 画布初始化,根据config配置为svg元素创建一个div class="djs-container"的父容器。并挂载到制定的dom节点上
 * 并在这个div节点下创建一个svg元素,挂载后面所有节点
 * 之后触发"diagram.init"与"canvas.init"
 * 同时注册'shape.added', 'connection.added', 'shape.removed', 'connection.removed', 'elements.changed', 'diagram.destroy', 'diagram.clear'
 * config: object 默认继承实例化BpmnModeler的配置
 */
Canvas._init(config)

/**
 * 画布销毁
 * 触发"canvas.destroy"
 * 删除Canvas内部属性,并移除初始化时声称的dom节点
 */
Canvas._destroy()

/**
 * 按类型创建新的元素对象, 同时触发对应的"[shape | connection].add"和"[shape | connection].added"事件,返回创建的元素对象(衍生的addShape,addConnection方法)
 * @param type: "shape" | "connection" 元素类型
 * @param element: object | djs.model
 * @param parent?: object | djs.model 父元素,默认为根元素对象
 * @param parentIndex?: number 
 * @return element: object | djs.model
 */
Canvas._addElement(type, element, parent, parentIndex)

/**
 * 移除对应的元素, 同时触发对应的"[shape | connection].remove"和"[shape | connection].removed"事件,返回被删除的元素对象(衍生的addShape,addConnection方法)
 * @param type: "shape" | "connection" 元素类型
 * @param element: object | djs.model
 * @param parent?: object | djs.model 父元素,默认为根元素对象
 * @param parentIndex?: number 
 * @return element: object | djs.model
 */
Canvas._removeElement(element, type)

方法与返回值:

// 返回最上层的SVGElement
Canvas.getDefaultLayer()

// 返回用于在其上绘制元素或注释的图层(这个不怎么理解。。。)
Canvas.getLayer(name, index)

// 返回包含画布的Dom节点
Canvas.getContainer()

/**
 * 将标记更新包element上(基本上是css类),同时触发"element.marker.update", 无返回值
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 */
canvas.addMarker(element, marker)


/**
 * 移除元素上的标记,同时触发"element.marker.update", 无返回值
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 */
canvas.removeMarker(element, marker)

/**
 * 检测元素是否具有某个标记
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 * @return status: boolean
 */
Canvas.hasMarker(element, marker)

/**
 * 切换元素的标记状态,存在即remove,不存在则add
 * @param element:Shape | Connaction | string(元素id)
 * @param marker: string
 */
Canvas.toggleMarker(element, marker)

/**
 * 返回画布的根元素
 * @return element: Object|djs.model
 */
Canvas.getRootElement()

/**
 * 设置新的画布的根元素,返回新的根元素
 * @param element:object | djs.model
 * @param override: boolean 是否要覆盖以前的根元素
 * @return element: Object|djs.model
 */
Canvas.setRootElement(element, override)

/**
 * 添加新的节点(形状)图形元素
 * @param shape: object | djs.model 插入的元素model或者属性配置对象
 * @param parent?: djs.model 父元素,默认根节点(画布下第一级SVG | Root)
 * @param parentIndex?: number 
 * @return Element: djs.model
 */
Canvas.addShape(shape, parent, parentIndex)

/**
 * 添加新的连线元素
 * @param Connaction: object | djs.model 插入的元素model或者属性配置对象
 * @param parent?: djs.model 父元素,默认根节点(画布下第一级SVG | Root)
 * @param parentIndex?: number 
 * @return Element: djs.model
 */
Canvas.addConnection(Connaction, parent, parentIndex)

/**
 * 移除节点元素, 返回被移除的节点
 * @param shape: string | djs.model 节点id或者model
 * @return element: djs.model
 */
Canvas.removeShape(shape)

/**
 * 移除连线元素, 返回被移除的对象
 * @param shape: string | djs.model 节点id或者model
 * @return element: djs.model
 */
Canvas.removeConnaction(connection)

/**
 * 查询图形元素的SVGElement,即 ElementRegistry.getGraphics()方法。
 * @param shape: string | djs.model 节点id或者model
 * @param secondary?: boolean 
 * @return element: SVGElement
 */
Canvas.getGraphics(element, secondary)

/**
 * 获取或者设置新的画布的视图框。该方法的getter可能会返回一个缓存中的viewbox(如果当前时刻视图正在发生改变)
 * 如果要强制重新计算,请先执行Canvas.viewbox(false)
 * @param box: Box 新的视图框配置
 * @param box.x: number = 0 视图框可见的画布区域在x轴坐标(原点左上角)
 * @param box.y: number = 0 视图框可见的画布区域在y轴坐标(原点左上角)
 * @param box.width: number 视图框可见宽度
 * @param box.height: number 视图框可见高度
 * @return box 当前视图区域
 */
Canvas.viewbox(box)

/**
 * 具有滚动条时调整滚动位置
 * @param delta:Delta 新的滚动位置
 * @param delta.dx:number x轴方向的位移大小
 * @param delta.dy:number y轴方向的位移大小
 * @return
 */
Canvas.scroll(delta)

/**
 * 设置新的缩放比例或者中心位置,返回当前的缩放比例
 * @param newScale?: number 新的缩放比例
 * @param center?: Point | "auto" | null
 * @param center.x: number
 * @param center.y: number
 * @return scale: number
 */
Canvas.zoom(newScale, center)

// 主动触发"canvas.resized"事件
Canvas.resized()

// 返回画布元素的大小
Canvas.getSize()

// 返回画布的绝对边界
// @return BBox {
    
// 		x: x;
// 		y: y;
// 		width: width;
// 		height: height;
// }
Canvas.getAbsoluteBBox()

5. EventBus 事件总线

核心模块之一,通用事件总线, 该组件用于跨图实例进行通信。 图的其他部分可以使用它来侦听和广播事件。

使用方式:

const EventBus = this.bpmnModeler.get("eventBus");

核心方法:

/**
 * 注册事件监听器
 * @param events: string | string[] 事件名称(s)
 * @param priority?: number 优先级,默认1000
 * @param callback: Function 回调函数
 * @param that?: object 上下文中的this,会将其传递给callback
 */
EventBus.on(events, priority, callback, that)
 
/**
 * 注册只执行一次的事件监听器
 * @param events: string | string[] 事件名称(s)
 * @param priority?: number 优先级,默认1000
 * @param callback: Function 回调函数
 * @param that?: object 上下文中的this,会将其传递给callback
 */
EventBus.once(events, priority, callback, that)
 
/**
 * 关闭、删除事件监听器
 * @param events
 * @param callback
 */
EventBus.off(events, callback)
 
/**
 * 创建一个可以让EventBus识别的事件,并返回这个事件
 * @param data: object
 * @return event: object
 */
EventBus.createEvent(data)

/**
 * 主动触发事件
 * @param type: string | object 事件名称/嵌套事件名称的对象({type: string})
 * @param data: any 传递给回调函数的参数 
 * @return status: boolean | any 事件返回值(如果指定);如果侦听器阻止了默认操作,则返回false
 */
EventBus.fire(type, data)

6. InternalEvent 事件

指通过事件总线发出来的事件实例。

/**
 * A event that is emitted via the event bus.
 */
function InternalEvent() {
     }

// 阻止事件传播给其他接收者
InternalEvent.prototype.stopPropagation = function() {
    
  this.cancelBubble = true;
};

// 阻止事件的默认结果
InternalEvent.prototype.preventDefault = function() {
    
  this.defaultPrevented = true;
};

InternalEvent.prototype.init = function(data) {
    
  assign(this, data || {
    });
};

事件可以结合事件总线对事件监听器做自定义处理。

比如:

EventBus.on("foo", function(event) {
    
    console.log(event.type) // "foo"
    event.stopPropagation(); // 停止事件继续传播
    event.preventDefault(); // 阻止事件原来的返回值,返回false
})

// 传入自定义信息
const payload = {
     fooPayload: "foo" }
EventBus.on("foo", function(event, payload) {
    
    console.log(payload) // { fooPayload: "foo" }
})

本文首发于“掘金”
作者:MiyueFE
链接:https://juejin.cn/post/6900793894263488519
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43359503/article/details/113915655

智能推荐

经典推送:针对jQuery升级踩坑大全_weixin_33953384的博客-程序员秘密

背景jQuery想必各个web工程师都再熟悉不过了,不过现如今很多网站还采用了很古老的jQuery版本。其实如果早期版本使用不当,可能会有 DOMXSS漏洞,非常建议升级到jQuery 1.9.x或以上版本。前段时间我就主导了这件事情,把公司里我们组负责的项目jQuery版本从1.4.2升级到了jQuery 1.11.3。jQuery官方也...

仿小米商城页面和简单效果_仿小米商城jsp_嘻嘻的博客-程序员秘密

&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;小米商城&lt;/title&gt; &lt;link rel="stylesheet" type="text/css" href="css/reset.css"&gt; &lt;link rel="stylesheet" type="text/css" href="css/fonts.css"&gt; &lt;l

C语言误差用什么变量,C语言-实型变量_weixin_39596090的博客-程序员秘密

实型变量1.实型数据在内存中的存放形式实型数据一般占4个字节(32位)内存空间。按指数形式存储。实数3.14159在内存中的存放形式如下:+.314159+1数符 小数部分 指符 指数小数部分占的位(bit)数愈多,数的有效数字愈多,精度愈高。指数部分占的位数愈多,则能表示的数值范围愈大。实际上,小数部分是一个二进制纯...

jquery的ul、li标签做菜单_li做菜单_水中鸟lgl的博客-程序员秘密

一、ulli标签做菜单知识点:1. 页面中的菜单项可以通过嵌套的ul和li来表示2. 浏览器中ul和li元素默认情况文字都有圆点标识符,li元素会有缩进。     List-style属性值为none时,可以清除ul和li前面的小圆点。3. 可以使用background-image来指定一个元素的背景图,如果背景图比元素的实际大小要小,那么背景图会自动在横向和纵向

di_项目di_Mashirolee的博客-程序员秘密

1.  简答题A.简述瀑布模型、增量模型、螺旋模型(含原型方法)的优缺点:    瀑布模型:有利于人员组织、管理;有利于软件开发工具研究;但是开发过程不能逆转,实践效率很低;对于客户来说等待时间过长。    增量模型:采用增量模型的优点是人员分配灵活,刚开始不用投入大量人力资源,如果核心产品很受欢迎,则可增加人力实现下一个增量,可先发布部分功能给客户。但是并行开发构件有可能遇到不能集成的风险,软件...

hdu3567 八数码2(康托展开+多次bfs+预处理)_weixin_30782293的博客-程序员秘密

Eight IITime Limit: 4000/2000 MS (Java/Others)Memory Limit: 130000/65536 K (Java/Others)Total Submission(s): 4103Accepted Submission(s): 878Problem DescriptionEight-puzzl...

随便推点

不能被连接,不能被扫描的,不带辅助广播包的ADV_EXT_IND的广播类型_adv ext ind_jacky_jin1的博客-程序员秘密

在ble5.0中,加入了广播包扩展的功能,广播跟原来的广播有比较大的改变,后面慢慢丰富。本文章只是探讨,不能被连接的,不能被扫描的,不带辅助广播包的ADV_EXT_IND的广播类型。ADV_EXT_IND 这个广播包类型,类似于是一个桥梁的作用,可以一方面,在传统的37 38 39上进行广播,一个辅助,在AUX_EXT_IND的广播类型。在此,不探讨,AUX_EXT_IND,如有兴趣,可...

核心案例|火工大分布式无人机协同控制研发平台_飞思实验室的博客-程序员秘密

火工大重点学科专业建设任务,主要为多智能体协同控制相关基础理论研究试验与关键技术演示验证提供条件支撑,为测控专业学员创新实践能力提供实验条件。

解决Spring5源码编译各种Gradle报错问题_spring源码编译指定gradle版本失效_栗子木的博客-程序员秘密

1. 前言最近希望能够学习一下Spring最新的源码,特意去GitHub上拉取Spring的源码.结果碰到各种Gradle报错问题,因为本人没有学习过Gradle,项目一直以来使用的都是Maven进行依赖管理.所以摸索过程中也是遇到各种问题,今天在这里给大家分享一下如何编译Spring的源码.2. 编译步骤 2.1拉取代码Spring源码托管在GitHub上,所以我们需要到GitHub上进行代码拉取https://github.com/spring-projects/sprin...

(转)代码重构_oldbalck的博客-程序员秘密

重构 重构(Refactoring)就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。  也许有人会问,为什么不在项目开始时多花些时间把设计做好,而要以后花时间来重构呢?要知道一个完美得可以预见未来任何变化的设计,或一个灵活得可以容纳任何扩展的设计是不存在的。系统设计人员对即将着手的项目...

Newsgroup18828文本分类器、文本聚类器、关联分析频繁模式挖掘算法的Java实现工程下载及运行FAQ_LarryNLPIR的博客-程序员秘密

Newsgroup18828文本分类器、文本聚类器、关联分析频繁模式挖掘算法的Java实现系列5篇博文自发表半年多来,累计浏览量近万次,Eclipse工程下载累计近千次,受到了很多朋友的关注,如果能给各位数据挖掘入门学习带来一些帮助本人感到很高兴。有很多朋友阅读代码成功运行工程输出了博文中展示的文本分类及聚类结果,但是有的朋友遇到编译失败或者配置路径错误等问题,半年来我也收到很多站内信和评论询问这

java、php、.net关于web开发的区别_张嘉楠2046的博客-程序员秘密

一提到web开发,目前在世界上流行性的三个帮派就是php,java和asp.net,这个世界上的百分之99的网站或者类似的应用都是由则三种语言的开发,这里请原谅我忽视某些小众语言如python之类。三种语言经过长达十几甚至二十多年的发展形成自己的生态圈,生态圈里面的世界千姿百态,生态圈外面的世界大漠黄沙、寒风凌厉。所以不管你是准备进入web开发的新人还是准备转型其它生态系统的老鸟,这篇文章都能给你

推荐文章

热门文章

相关标签