聊一聊bpmn-js中的elementFactory模块

上一篇文章里我们了解了bpmn-js使用palette模块进行左侧小工具区域(也可以理解为调色板区域)的功能扩展,今天这个话题则是延续上期的palette进行开展的。


聊一聊bpmn-js中的elementFactory模块


从上篇文章《聊一聊bpmn-js中的Palette》我们知道,PaletteProvider通过getPaletteEntries方法提供小工具Map对象,而单个小工具绘制对象格式如下:

type PaletteEntry = {
action
: (event: Event, autoActivate: boolean) => any || {}; // 事件回调,或者是事件对象如{dragStart:()=>{}}
className
?: string; // 类名,这里可用作加载字体图标
group?: string; // 区域划分
html
?: string; // 自定义html显示
imageUrl
?: string; // 图标链接地址
separator
?: boolean;
title
?: string; // 悬停显示文字
};

这里action作为palette与主建模编辑的交互模块,palette中引用了elementFactorycreate模块进行绘制创建和管理。而本篇文章我们的主角就是工具的元素创建工具类:ElementFactory,其插件模块位于diagram-js/lib/core/ElementFactory.js,在PaletteProvider中的使用如下:

// 声明注入模块
PaletteProvider.$inject = [
......
'create',
'elementFactory',
......
];
// 初始化
export default function PaletteProvider(...,create, elementFactory,...){
......
this._create = create;
this._elementFactory = elementFactory;
......
}


PaletteProvider.prototype.getPaletteEntries = function() {
function createAction(type, group, className, title, options){
// 事件交互创建shape
function createListener(event) {
var shape = elementFactory.createShape(assign({ type: type }, options));
if (options) {
var di = getDi(shape);
di
.isExpanded = options.isExpanded;
}
create
.start(event, shape);
}
}
......
}

上述可以发现,元素的绘制包括两个模块:elementFactorycreatecreate主要是处理触发事件后的动作操作,elementFactory用于创建当前元素,本篇文章主要来介绍diagram-js中的elementFactory模块。

元素类型

elementFactorydiagram-js中用于提供创建元素模型的一个工厂类,主要还是以创建元素模型为主(即元素结构,元素绘制由单独的defaultRenderer模块负责)。在elementFactory模块中将元素的模型分为四类,当且仅当绘制的类型是这四类才能成功创建,否则将会抛出异常:unknown type

elementFactory的元素类型通过一个变量来定义控制,这也是为了便于扩展,日后由其他新增的类型也不是没有可能的,且所有类型都是基于基础类型ElementImpl的基础上进行的扩展,我们可以通过代码了解:

var types = {
connection
: ConnectionImpl,
shape
: ShapeImpl,
label
: LabelImpl,
root
: RootImpl
};

// 基础类型
function ElementImpl() {
Object.defineProperty(this, 'businessObject', {
writable
: true
});

Object.defineProperty(this, 'label', {
get: function() {
return this.labels[0];
},
set: function(newLabel) {

var label = this.label,
labels
= this.labels;

if (!newLabel && label) {
labels
.remove(label);
} else {
labels
.add(newLabel, 0);
}
}
});

// 实现关联元素的双向引用
parentRefs
.bind(this, 'parent');
labelRefs
.bind(this, 'labels');
outgoingRefs
.bind(this, 'outgoing');
incomingRefs
.bind(this, 'incoming');
}

通过上述代码可以发现ElementImpl给所有元素定义了一些基础实现和绑定:

  • businessObject:这是元素的属性信息汇总对象

  • label:支持单标签,将映射到多标签阵列

  • 绑定: ElmenetImpl实现了元素的父类、流入、流出、多标签绑定

elementFactory中的所有绑定关系将会交由elementFactory模块内部统一维护:

var parentRefs = new Refs({ name: 'children', enumerable: true, collection: true }, { name: 'parent' }),
labelRefs
= new Refs({ name: 'labels', enumerable: true, collection: true }, { name: 'labelTarget' }),
attacherRefs
= new Refs({ name: 'attachers', collection: true }, { name: 'host' }),
outgoingRefs
= new Refs({ name: 'outgoing', collection: true }, { name: 'source' }),
incomingRefs
= new Refs({ name: 'incoming', collection: true }, { name: 'target' });

1、connection

connection元素就是连接线用于将两个元素进行连接,其中主要包含定义元素来源和元素流入的方向绑定:

function ConnectionImpl() {
ElementImpl.call(this);

// 来源于
outgoingRefs
.bind(this, 'source');

// 流向
incomingRefs
.bind(this, 'target');
}

// 创建示例
import * as Model from 'diagram-js/lib/model';

const connection = Model.create('connection', {
waypoints
: [
{ x: 100, y: 100 },
{ x: 200, y: 100 }
]
});

2、shape

shape类型主要就是用于创建有形状的元素,类似开始、流程、判断等工作流元素。

function ShapeImpl() {
ElementImpl.call(this);

// 绑定子元素
parentRefs
.bind(this, 'children');
attacherRefs
.bind(this, 'host');
attacherRefs
.bind(this, 'attachers');
}

// 创建示例
import * as Model from 'diagram-js/lib/model';

const shape = Model.create('shape', {
x
: 100,
y
: 100,
width
: 100,
height
: 100
});

3、label

label类型主要是给其他元素提供文字管理,它继承于一个shape类型,而非基础的element类型。

function LabelImpl() {
ShapeImpl.call(this);


labelRefs
.bind(this, 'labelTarget');
}
// 示例创建
import * as Model from 'diagram-js/lib/model';

const label = Model.create('label', {
x
: 100,
y
: 100,
width
: 100,
height
: 100
labelTarget
: shape
});

4、root

这里就是当前bpmn-js流程图的根节点了,也就是bpmn:process元素,更节点包含的元素较为简单主要是存在与所有子元素的关联:

function RootImpl() {
ElementImpl.call(this);


parentRefs
.bind(this, 'children');
}

// 示例创建
import * as Model from 'diagram-js/lib/model';

const root = Model.create('root', {
x
: 100,
y
: 100,
width
: 100,
height
: 100
});

工厂方法

elementFactory提供的工厂方法比较直球,基本你看到方法名称就知道它是创建什么元素的:

  • createRoot:创建root元素

  • createLabel:创建label

  • createShape:创建带有形状的元素

  • createConnection:创建连接线

  • create:这是所有工厂方法的实现


原文始发于微信公众号(胖蔡话前端):聊一聊bpmn-js中的elementFactory模块

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/222913.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!