胖蔡说技术
随便扯扯

聊一聊bpmn-js中的elementFactory模块

bpmn-js 阅读指南:

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

从上篇文章《聊一聊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:这是所有工厂方法的实现
赞(0) 打赏
转载请附上原文出处链接:胖蔡说技术 » 聊一聊bpmn-js中的elementFactory模块
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

请小编喝杯咖啡~

支付宝扫一扫打赏

微信扫一扫打赏