蓝海豹

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

https://blog.csdn.net/u013253924/article/details/85784002

通过本文逐步熟悉bpmn-js。

 

快速介绍:

bpmn.js是一个BPMN2.0渲染工具包和web建模器。使用JavaScript编写,在不需要后端服务器支持的前提下向现代浏览器内嵌入BPMN2.0流程图。这使得它很容易的嵌入到任何web应用中。

 

这个库既可以是web查看器也可以是web建模器。使用查看器将BPMN2.0流程图嵌入到你的应用中并可以使用数据丰富你的流程图。使用建模器在你的应用内部创建BPMN2.0流程图。

 

下文将向您介绍如何使用该库,并深入了解其内部结构。也就是说,这两个组件促成了该库的高度模块化和可扩展的结构。

 

本文包含以下内容:

 

● 如何使用库

   • 嵌入查看器(预打包)

   • 自己制作模型(通过npm)

● 理解bpmn-js内部

   • 流程图交互/建模(流程图-js)

   • BPMN元模型(bpmn-moddle)

   • 将事物整合在一起(bpmn-js)

● 进一步探索

 

如何使用库

 

有两种方法在你的应用中使用bpmn.js。库的预打包版本可以让你在任何网站中快速添加BPMN。npm版本的设置更加复杂,但允许您访问单个库组件,并更容易扩展。

本节将概述这两种方法。首先我们来介绍如何向网站中嵌入一个预打包的BPMN查看器。之后,展示如何通过npm创建一个BPMN建模器。

 

嵌入预打包查看器

通过一个简单的script标签引入就可以将预打包的BPMN查看器嵌入你的网站

  1.  
    <!-- BPMN 流程图容器 -->
  2.  
    <div id="canvas"></div>
  3.  
    <!-- 使用 CDN 路径 或者本地 bpmn-js 路径 -->
  4.  
    <script src="https://unpkg.com/bpmn-js@0.27.0-1/dist/bpmn-viewer.development.js"></script>

 

通过引入的BPMNjs变量,可以使BPMN查看器可用。我们可以通过下面这段js来引入一个BPMN流程图。

  1.  
    <script>
  2.  
    // 你即将要展示的流程图
  3.  
    var bpmnXML;
  4.  
    // BpmnJS是BPMN查看器实例
  5.  
    var viewer = new BpmnJS({ container: '#canvas' });
  6.  
    // 导入BPMN 2.0流程图
  7.  
    viewer.importXML(bpmnXML, function(err) {
  8.  
    if (err) {
  9.  
    //导入失败 !
  10.  
    } else {
  11.  
    // 导入成功!
  12.  
    var canvas = viewer.get('canvas');
  13.  
    canvas.zoom('fit-viewport');
  14.  
    }
  15.  
    });
  16.  
    </script>

该代码片段使用Viewer#importXML API显示预加载的BPMN 2.0图。导入图是异步的,一旦完成,查看器将通过回调通知我们结果。

导入后,我们可以通过Viewer#get访问各种图表服务。在上面的代码片段中,我们与画布交互以使图适合当前可用的视图大小。

通常,通过AJAX动态加载BPMN 2.0图更实用。这可以使用纯JavaScript(如下所示)或通过实用程序库(如jQuery)实现,后者提供了更方便的api。

  1.  
    <script>
  2.  
    var xhr = new XMLHttpRequest();
  3.  
    xhr.onreadystatechange = function() {
  4.  
    if (xhr.readyState === 4) {
  5.  
    viewer.importXML(xhr.response, function(err) {
  6.  
    // ...
  7.  
    });
  8.  
    }
  9.  
    };
  10.  
    xhr.open('GET', 'path-to-diagram.bpmn', true);
  11.  
    xhr.send(null);
  12.  
    </script>

查看预打包的示例以及我们的初学者示例,了解更多信息。

 

创建属于自己的建模器

 

如果你想要围绕库做一些定制化,需要使用npm来使用库。这种方法有很多优点,比如可以访问单个库组件。它还使我们能够更好地控制部分打包查看器/建模器。需要使用Webpack (>=2) or Rollup来打包bpmn-js和我们的应用。

以下大致遵循modeler示例,使用该库创建BPMN建模器。

 

引入库

 

首先,通过npm安装bpmn.js

npm install bpmn-js

然后,通过ES import获得BPMN建模器

import Modeler from 'bpmn-js/lib/Modeler';

// 创建一个建模器

var modeler = new Modeler({ container: '#canvas' });

 

// 导入流程图

  1.  
    modeler.importXML(bpmnXML, function(err) {
  2.  
    // ...
  3.  
    });

同样的,需要在你的html中提供一个id声明的画布元素,以便建模器能够向画布内渲染。

 

添加样式

 

当将建模器嵌入网页时,要引入diagram-js样式以及BPMN图标字体。它们都随bpms -js发行版一起在dist/assets文件夹下提供。

  1.  
    <link rel="stylesheet" href="bpmn-js/dist/assets/diagram-js.css" />
  2.  
    <link rel="stylesheet" href="bpmn-js/dist/assets/bpmn-font/css/bpmn-.css" />

添加样式表可以确保图元素获得适当的样式化,背景板以及画板显示BPMN图标

 

浏览器打包

 

bpmn.js及其依赖由ES模块分发。使用ES模块打包器Webpack (>=2) 或者 Rollup来打包bpmn.js和你的应用。可以通过打包例子来学习更多相关。

 

与生命周期事件挂钩

 

事件允许您钩入建模器的生命周期以及图交互。下面的代码片段展示了一般情况下如何捕获元素的更改和建模操作。

  1.  
    modeler.on('commandStack.changed', function() {
  2.  
    // 建模或执行撤销/重做操作
  3.  
    });
  4.  
    modeler.on('element.changed', function(event) {
  5.  
    var element = event.element;
  6.  
    // 元素改变触发
  7.  
    })

 

使用Viewer#on注册事件或者扩展模块中的事件总线。使用 Viewer#off 来停止监听事件。请查看交互示例,以查看监听动作中的事件。

 

建模器的扩展

 

在实际使用的过程中,你可以用additionalModules选项来扩展查看器和建模器。允许您使用自定义模块来修改或替换现有的功能。

 

import OriginModule from 'diagram-js-origin';


 

  1.  
    // 创建一个建模器
  2.  
    var modeler = new Modeler({
  3.  
    container: '#canvas',
  4.  
    additionalModules: [
  5.  
    OriginModule,
  6.  
    require('./custom-rules'),
  7.  
    require('./custom-context-pad')
  8.  
    ]
  9.  
    });
  10.  
     

一个模块(比较:模块系统部分)是一个单元,定义了一个或多个服务。这些服务配置了bpmn.js或者提供了额外的功能。也就是通过接入流程图的生命周期来实现的。

 

一些模块,例如: diagram-js-origin 或 diagram-js-minimap提供了通用的用户界面添加。内置的bpmn-js模块,例如:such as bpmn rules 或 modeling提供了高定制的BPMN功能。

 

常用扩展BPMN建模器的方法是添加“自定义建模规则”。这样,您可以限制或扩展用户的建模操作。

 

扩展的其他例子有:

 

● 添加自定义元素

● 自定义面板/内容面板

● 自定义形状的渲染

 

查看bpms -js-example项目,了解更多工具包扩展展示案例。

 

构建自定义发行版

如果你想要针对你自定义的建模器和查看器创建预打包版本,请参 custom-bundle example这个例子。如果你定制了大量的功能但是希望以简单的方式交付给用户的话,这可能会给到你帮助。

 

理解bpmn-js内部

本节探讨一些bpmn-js的内部结构。

如下面的架构图所示,bpmn-js构建在两个重要的库之上:diagram-js和bpmn-moddle。

 

 

我们使用diagram-js 来绘制形状和连接。它为我们提供了与这些图形元素交互的方法,同时也提供了额外的工具例如overlays来帮助用户构建更为强大的查看器。对于更高级的建模情况,提供了提供了背景板、调色板和重做/撤消等功能。

bpmn-moddle清楚BPMN2.0元模型,元模型定义在BPMN2.0规范之上。它允许我们读写BPMN 2.0模式兼容的XML文档,获得关于图形和连接的相关信息并绘制出来。

在这两个库之上,bpmn.js定义了BPMN的细节,比如外观、建模规则和工具(如调色板)。我们将在下面的段落中详细介绍各个组件。

 

图交互/建模(diagram-js)

diagram-js是一个工具箱,用于在web上显示和修改图表。它允许我们渲染视觉元素并在它们之上构建交互体验。它为我们提供了一个非常简单的模块系统,用于构建特殊的服务和服务的依赖注入。这个系统还提供了一些核心服务,这些服务实现了图的基本内容。

此外,diagram-js为图形元素及其关系定义了一个数据模型。

 

模块系统

再下一层,diagram-js使用依赖注入(DI)来连接和发现图组件。这个机制是建立在node-di之上的。

在diagram-js上下文中讨论模块时,我们指的是提供命名服务及其实现的单元。从这个意义上说,服务是一个函数或实例,它可以使用其他服务在图的上下文中执行某些操作。

 

下面显示了一个与生命周期事件挂钩的服务。它通过eventBus注册一个事件来实现,eventBus是另一个著名的服务:

  1.  
    function MyLoggingPlugin(eventBus) {
  2.  
    eventBus.on('element.changed', function(event) {
  3.  
    console.log('element ', event.element, ' changed');
  4.  
    });
  5.  
    }

 

// 确保依赖项名称在缩小后仍然可用

MyLoggingPlugin.$inject = [ 'eventBus' ];

 

我们必须使用模块定义唯一名称发布服务:

import CoreModule from 'diagram-js/lib/core';

  1.  
    // 作为一个模块导入
  2.  
    export default {
  3.  
    __depends__: [ CoreModule ], // {2}
  4.  
    __init__: [ 'myLoggingPlugin' ], // {3}
  5.  
    myLoggingPlugin: [ 'type', MyLoggingPlugin ] // {1}
  6.  
    };

 

该定义告诉DI基础设施,该服务名为myLoggingPlugin {1},它依赖于diagram-js核心模块{2} 并且服务应该在创建关系图{3}时初始化。要了解更多细节,请查看node-di的文档。

 

我们现在可以通过我们的自定义模块引导diagram-js

要将模块插入bpmn-js,可以使用additionalModules选项,如扩展Modeler部分所示。

 

核心服务

bpmn-js核心是围绕一些基本服务构建的:

 

● Canvas -提供了添加和删除图形元素的api;处理元素生命周期,并提供用于缩放和滚动的api。

● EventBus -该库的全局通信通道具有防火和遗忘策略。可以订阅各种事件,并在事件发出后立即采取行动。事件总线帮助我们解耦关注点并模块化功能,以便新特性能够轻松地与现有行为挂钩。

● ElementFactory -根据bpmn-js的内部数据模型创建形状和连接的工厂。

● ElementRegistry—知道添加到图中的所有元素,并提供api来根据id检索元素及其图形表示。

● GraphicsFactory -负责创建图形和连接的图形表示。实际的外观是由渲染器定义的,即绘制模块中的DefaultRenderer。

 

数据模型

实际上,diagram-js实现了一个由形状和连接组成的简单数据模型。

 

数据模型要点:形状和连接

一个形状有父节点、子节点列表以及传入和传出连接列表。

一个连接有父节点、源节点和目标节点,指向一个形状。

ElementRegistry负责根据该模型创建形状和连接。

在建模过程中,建模服务将根据用户操作更新元素关系。

 

辅助服务(即工具箱)

除了数据模型及其核心服务之外,diagram-js还提供了丰富的辅助工具工具箱。

CommandStack-负责建模过程中的重做和撤销。

● ContextPad-提供一个元素的上下文操作。

● Overlays——提供api来附加额外的信息到图元素。

● Modeling——提供用于更新画布上的元素(移动、删除)的api

● Palette

让我们继续讨论幕后发生的BPMN魔法。

 

BPMN元模型(bpmn-moddle)

bpmn-moddle封装了BPMN 2.0元模型,为我们提供了读写BPMN 2.0 XML文档的工具。在导入时,它将XML文档解析为JavaScript对象树。在建模过程中对该树进行编辑和验证,然后在用户希望保存图时将其导出回BPMN 2.0 XML。因为bpmn-moddle封装了有关BPMN的知识,我们能够在导入和建模期间进行验证。根据结果,我们可以约束某些建模操作,并向用户输出有用的错误消息和警告。

就像bpmn-js一样,bpmn-moddle的基础也是建立在两个库之上的:

● moddle提供了一种用JavaScript定义元模型的简洁方法

● 基于moddle读写XML文档的model-xml

 

从本质上讲,bpmn-moddle将BPMN规范作为元模型添加进来,并为BPMN模式验证提供了一个简单的接口。从库的角度来看,它提供了以下API:

● fromXML -从给定的XML字符串创建BPMN树

● toXML - 向BPMN 2.0 XML编写BPMN对象树

 

BPMN元模型对于bpmn -js是必不可少的,因为它允许我们验证我们使用的BPMN 2.0文档,提供正确的建模规则,并导出所有遵循BPMN模型的人都能理解的有效BPMN文档。

 

把东西连接起来(bpmn-js)

 

我们学过bpms -js是建立在diagram-js和bpms -moddle之上的。它将两者联系在一起,并添加BPMN外观。这包括BPMN调色板、BPMN背景板以及BPMN 2.0特定规则。在本节中,我们将解释它在建模的不同阶段是如何工作的。

当我们导入BPMN 2.0文档时,bpmn-moddle会将其从XML解析为对象树。bpmn-js呈现该树的所有可见元素,即在画布上创建各自的形状和连接。因此,它将BPMN元素和图形元素联系在一起。这将产生一个结构,如下所示,用于初始事件形状。

{

id: 'StartEvent_1',

x: 100,

y: 100,

width: 50,

height: 50,

businessObject: {

$attrs: Object

$parent: {

$attrs: Object

$parent: ModdleElement

$type: 'bpmn:Process'

flowElements: Array[1]

id: 'Process_1'

isExecutable: false

}

$type: 'bpmn:StartEvent'

id: 'StartEvent_1'

}

}

 

您可以通过businessObject属性从每个图形元素访问底层BPMN类型。

 

由于BpmnRenderer,bpmn -js也知道每个BPMN元素的样子。通过插入渲染周期,您还可以定义单个BPMN元素的自定义表示。

 

一旦导入完成,我们就可以开始建模了。我们使用规则来允许或不允许某些建模操作。这些规则由BpmnRules定义。我们将这些规则基于OMG定义的BPMN 2.0标准。然而,正如前面提到的,其他人也可能与规则评估挂钩,以贡献不同的行为。

 

建模模块捆绑了BPMN 2.0相关的建模功能。它添加了BPMN 2.0特定的建模行为,并负责在用户执行的每个建模操作中更新BPMN 2.0文档树(cf. BpmnUpdater)。请查看它,以更深入地了解规则、行为和BPMN更新周期。

 

当纯粹从库的角度来看bpmn-js时,值得一提的是它可以有三种形式:

 

● Viewer展示图

● NavigatedViewer显示和导航BPMN图

● Modeler 建模BPMN图

 

版本之间的唯一区别是它们捆绑了不同的功能集。NavigatedViewer添加了用于导航画布的模块,Modeler添加了大量用于创建、编辑和与画布上的元素交互的功能。

posted on 2019-04-17 14:25  蓝海豹  阅读(3339)  评论(0编辑  收藏  举报