Bpmn-js快速入门
1、功能介绍bpmn-js是一个渲染工具包和一个(流程节点)建模器的结合。在使用的时候,既可以是查看模式,也可以是建模(编辑)模式。1.1、以代码包形式使用查看器通过在浏览器引入bpmn-viewer,然后使用BpmnJS创建查看器对象,读取bpmnXml配置文件即可。let viewer = new BpmnJS({container: '#canvas'});viewer.importXML(
1、功能介绍
bpmn-js是一个渲染工具包和一个(流程节点)建模器的结合。在使用的时候,既可以是查看模式,也可以是建模(编辑)模式。
1.1、以代码包形式使用查看器
通过在浏览器引入bpmn-viewer,然后使用BpmnJS创建查看器对象,读取bpmnXml配置文件即可。
let viewer = new BpmnJS({container: '#canvas'});
viewer.importXML(bpmnXml, function(err) {
if (err) {
} else {
let canvas = viewer.get('canvas');
canvas.zoom('fit-viewport'); // 适应当前可以区域大小
}
});
1.2、使用建模器
1.2.1、创建建模器对象
创建自定义建模器,必须使用npm方式将bpmn-js引入项目中。
import Modeler from 'bpmn-js/lib/Modeler';
// 创建建模器对象
let modeler = mew Modeler({container: '#canvans'});
// 读取流程配置
modeler.importXML(bpmnXml, function(err) {
// 执行后续处理
});
1.2.2、添加默认样式
引入建模器默认样式到页面中。
<link rel="stylesheet" href="bpmn-js/dist/assets/diagram-js.css" />
<link rel="stylesheet" href="bpmn-js/dist/assets/bpmn-font/css/bpmn.css" />
或
@import 'bpmn-js/dist/assets/diagram-js.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
1.2.3、注册生命周期事件监听
// 给建模器注册元素变更事件
modeler.on('element.changed', function(e) {
let ele = e.element;
});
// 给查看器注册元素交互事件
let eventBus = viewer.get('eventBus');
evnetBus.on('element.hover', function(e) {
console.log(e.element.id);
});
// 元素事件有:element.hover、click、dbclick、mousedown、mounseup
甚至可以直接注册原生的DOM事件监听,因为每一个元素都被默认添加了一个key为data-element-id的自定义特征。
1.2.4、建模器扩展
可以使用附加模块在创建的时候拓展查看器和建模器,通过自定义模块修改或替换原有功能。
// 引入原始模块
import OriginModule from 'diagram-js-origin';
// 引入自定义拓展
import CustomRules from './custom-rules';
import CustomContextPad from './custom-context-pad';
// 拓展建模器
let modeler = new Modeler({
container: '#canvas',
additionalModules: [
OriginModules,
CustomRules,
CustomContextPad
]
});
查看3.3拓展示例
2、内部原理介绍
bpmn-js构建在两个插件库之上:
- bpmn-moddle:用于读写bpmnXml文档,等于元数据模型定义器。如果要拓展bpmnXml中支持的标签,看来就要拓展这货了。
- diagram-js:用于绘制图表的形状,连线,触发图表事件等。
bpms-js在其之上,建立文档和图表渲染之间的对应关系。
2.1、diagram 图表交互与模型
diagram-js是一个用于在页面上绘制和修改图表的工具集,用于渲染虚拟元素并在其上构建用户体验。它提供了一个用于构建图表模块的简单模型和核心实现服务,同时建立了一套针对图形元素及其关系的数据模型。
2.1.1、模块系统模型
diagram使用依赖注入方式发现和装配虚拟图表组件,底层依赖didi插件。
ps: 依赖注入
didi插件是一个专门的js版依赖注入控制容器。
依赖注入di又叫控制反转ioc,的典型实现是spring,就是通过配置来向引擎注册需要的或者自定义的组件。
依赖注入使组件和组件依赖的实例化与组件行为脱钩,可以起到如下作用:
- 显式展示依赖项 – 所有依赖项都作为构造函数传递。
- 代码重用 – 实现了组件间解耦。
- 更易测试。
didi通过声明各个组件的依赖关系,由框架对其进行管理,并且传递性的对依赖对象进行实例化。
import { Injector } from 'didi';
// 声明构造函数Car,Car的实例依赖Engine对象的实例
function Car(engine) {
this.start = function() {
engine.start();
}
}
// 工厂模式构造函数,返回一个Engine对象
function createPetrolEngine(power) {
return {
start: function() {
console.log('start with' + power + 'hp');
}
}
}
// 声明Car模块
const carMoudle = {
// 声明car变量的构造函数
'car': ['type', Car],
// 声明engine变量的构造方式
'engine': ['factory', createPetrolEngine],
// 声明基本类型变量的值
'power': ['value', 1184]
};
const injector = new Injector([
carMoudle
]);
// 实例化(注入)模块
injector.invoke(function(car) {
car.start();
});
diagram中的modules(模块)指的是能够提供特定服务的一个函数或者实例单元。使用didi在diagram中定义一个module的方式如下示例:
// filename path-to-my-logging-module
import CoreModule from 'diagram-js/lib/core';
// 定义模块服务,该服务为查看器的元素变动事件添加日志纪录功能
function MyLoggingPlugin(eventBus) {
eventBus.on('element.changed', function(event) {
console.log('element', event.element, 'change');
});
}
// 声明该服务需要注入的变量
MyLoggingPlugin.$inject = [ 'eventBus' ];
// 声明并对外暴露模块
export default {
__depends__: [ CoreModule ], // 声明该模块依赖
__init__: ['MyLoggingPlugin'], //声明该模块需要在系统初始化的时候被调用
myLoggingPlugin: [ 'type', MyLoggingPlugin ] //声明该模块的构造函数
}
// file MyDiagram
import MyLoggingPlugin from './path-to-my-logging-module';
let diagram = new Diagram({
modules: [
MyLoggingPlugin
]
});
export default diagram;
// 使用1.2.4的additionalModules可以将MyDiagram引入建模器
2.1.2、核心服务对象
- Canvas:提供图形元素新增和移除接口,管理图形元素声明周期,提供图形拖动和页面适应处理等接口。
- EventBus:事件总线,集成化的提供事件注册和分发功能。
- ElementFactory:元素工厂,根据diagram内部数据模型创建图形和连接线。
- GraphicalFactory:图形工厂,创建图形和连接线,实际效果由渲染器(DefaultRenderer)实现。
2.1.3、内部数据模型
diagram为图形和连接线创建了一个简单的数据模型。
- 一个图形具有一个父节点,一个子节点列表,和一个包含流入和流出连接线的列表。
- 一个连接线具有一个父链接,还有指向的源图形和目标图形。
系统使用ElementRegistory对象根据数据模型进行图形和连接线的生成。
2.1.4、辅助工具
- CommonStock:命令栈,用于重做和回退操作。
- ContextPad:上下文面板,提供围绕元素上下文操作。
- Overlays:层级工具,提供将其他信息附加到图形元素上的接口。
- Modeling:模型工具,提供用于更新画布元素(如移动,删除)的接口。
2.2、bpmn-moddle
bpmn-moddle(以下称为BM)用于封装bpmn2.0元数据模型,并提供了读写bpmnXml的方法,它将xml文件解析为对象树,该树在建模期间编辑和验证,并在保存建模的时候导出为xml。
BM建立在两个核心库之上:
- moddle:对象树定义和处理
- moddle-xml :基于moddle库读写xml文档。
在核心库之上BM提供了简单的操作接口,比如:
- fromXML
- toXML
2.3、整合diagram与BM
bpmn-js使用BM将xml文件解析为对象树,然后建立对象树中的示例(bpmn元素)与diagram中的图形和连接线之间的联系(混合对象),从而在diagram的Canvas上渲染出图表节点来。一个图形元素对象如下示例:
{
id: 'StartEvent_1',
x: 100,
y: 100,
width: 50,
height: 50,
businessObject: {
$attrs: Object,
$type: 'bpmn:StartEvent',
id: 'StartEvent_1',
$parent: {
$attrs: Object,
$parent: ModdleElement,
$type: 'bpmn:Process',
flowElements: Array[1],
id: 'Process_1',
isExecutable: false
}
}
}
可以使用businessObject属性从每个图形元素访问到bpmn对象。
3、示例分析
3.1、为图形元素添加颜色
3.1.1、方案1 – 使用层叠蒙版
viewer.import(diagramXml, function() {
// 1、使用viewer获得层叠对象和元素注册器
let overlays = viewer.get('overlays');
let elementRegistry = viewer.get('elementRegistry');
// 2、获得要添加颜色的图形元素,目的是获得该元素的尺寸数据
let shape = elementRegistry.get('UserTask_1');
// 3、使用jquery创建一个DOM,尺寸与图形元素相同
let $overlayhtml = $('<div class="height-overlay">').css({
width: shape.width,
height: shape.height
});
// 4、使用overlays对象为图形元素添加蒙版层
overlays.add('UserTask_1', {
position: {
top: -5,
left: -5
},
html: $overlayhtml
});
});
3.1.2、方案2 – 自定义图形元素的颜色拓展
可以使用模型器(或查看器,这两个对象的区别仅仅是可不可编辑diagram,他们拥有的服务应该差不多)的Modeling对象(的setColor方法)将颜色加入到的bpmn模型中。
// 接3.1.1
// 获取modleing对象(或者叫服务)
let modeling = viewer.get('modeling');
// 添加颜色,setColor第一个参数是图形元素对象的数组,第二个参数是颜色配置
modeling.setColor([ shape ], {
stroke: 'green',
fill: 'rgba(0, 80, 0, 0.4)'
});
3.2、元素模型
每一个diagram元素对象都可以通过businessObject属性获得对应的底层模型对象的引用。而business Object是根据bpmnXml配置生成的,可以用于读取和设置元素属性。
通过bpmn对象的moddleExtensions配置,可以json的方式自定义元素模型,事实上bpmn默认就拥有上百个类型的元素。
使用元素工厂对象elementsFactory,可以创建json定义中存在的任意元素对象,并设置对象的属性。
3.2.1、元素类型
bpmn默认元素
类型名称 | 父类型 | 属性 |
---|---|---|
Interface | RootElement | name(String), operations(Operation), implementationRef(String), |
Operation | BaseElement | name(String), inMessageRef(Message), outMessageRef(Message), errorRef(Error), implementationRef(String), |
EndPoint | RootElement | |
Auditing | BaseElement | |
GlobalTask | CallableElement | resources(ResourceRole), |
Monitoring | BaseElement | |
Performer | ResourceRole | |
Process | FlowElementsContainer,CallableElement | processType(ProcessType), isClosed(Boolean), auditing(Auditing), monitoring(Monitoring), properties(Property), laneSets(LaneSet), flowElements(FlowElement), artifacts(Artifact), resources(ResourceRole), correlationSubscriptions(CorrelationSubscription), supports(Process), definitionalCollaborationRef(Collaboration), isExecutable(Boolean), |
LaneSet | BaseElement | lanes(Lane), name(String), |
Lane | BaseElement | name(String), partitionElementRef(BaseElement), partitionElement(BaseElement), flowNodeRef(FlowNode), childLaneSet(LaneSet), |
GlobalManualTask | GlobalTask | |
ManualTask | Task | |
UserTask | Task | renderings(Rendering), implementation(String), |
Rendering | BaseElement | |
HumanPerformer | Performer | |
PotentialOwner | HumanPerformer | |
GlobalUserTask | GlobalTask | implementation(String), renderings(Rendering), |
Gateway | FlowNode | gatewayDirection(GatewayDirection), |
EventBasedGateway | Gateway | instantiate(Boolean), eventGatewayType(EventBasedGatewayType), |
ComplexGateway | Gateway | activationCondition(Expression), default(SequenceFlow), |
ExclusiveGateway | Gateway | default(SequenceFlow), |
InclusiveGateway | Gateway | default(SequenceFlow), |
ParallelGateway | Gateway | |
RootElement | BaseElement | |
Relationship | BaseElement | type(String), direction(RelationshipDirection), source(Element), target(Element), |
BaseElement | id(String), documentation(Documentation), extensionDefinitions(ExtensionDefinition), extensionElements(ExtensionElements), | |
Extension | mustUnderstand(Boolean), definition(ExtensionDefinition), | |
ExtensionDefinition | name(String), extensionAttributeDefinitions(ExtensionAttributeDefinition), | |
ExtensionAttributeDefinition | name(String), type(String), isReference(Boolean), extensionDefinition(ExtensionDefinition), | |
ExtensionElements | valueRef(Element), values(Element), extensionAttributeDefinition(ExtensionAttributeDefinition), | |
Documentation | BaseElement | text(String), textFormat(String), |
Event | FlowNode,InteractionNode | properties(Property), |
IntermediateCatchEvent | CatchEvent | |
IntermediateThrowEvent | ThrowEvent | |
EndEvent | ThrowEvent | |
StartEvent | CatchEvent | isInterrupting(Boolean), |
ThrowEvent | Event | dataInputs(DataInput), dataInputAssociations(DataInputAssociation), inputSet(InputSet), eventDefinitions(EventDefinition), eventDefinitionRef(EventDefinition), |
CatchEvent | Event | parallelMultiple(Boolean), dataOutputs(DataOutput), dataOutputAssociations(DataOutputAssociation), outputSet(OutputSet), eventDefinitions(EventDefinition), eventDefinitionRef(EventDefinition), |
BoundaryEvent | CatchEvent | cancelActivity(Boolean), attachedToRef(Activity), |
EventDefinition | RootElement | |
CancelEventDefinition | EventDefinition | |
ErrorEventDefinition | EventDefinition | errorRef(Error), |
TerminateEventDefinition | EventDefinition | |
EscalationEventDefinition | EventDefinition | escalationRef(Escalation), |
Escalation | RootElement | structureRef(ItemDefinition), name(String), escalationCode(String), |
CompensateEventDefinition | EventDefinition | waitForCompletion(Boolean), activityRef(Activity), |
TimerEventDefinition | EventDefinition | timeDate(Expression), timeCycle(Expression), timeDuration(Expression), |
LinkEventDefinition | EventDefinition | name(String), target(LinkEventDefinition), source(LinkEventDefinition), |
MessageEventDefinition | EventDefinition | messageRef(Message), operationRef(Operation), |
ConditionalEventDefinition | EventDefinition | condition(Expression), |
SignalEventDefinition | EventDefinition | signalRef(Signal), |
Signal | RootElement | structureRef(ItemDefinition), name(String), |
ImplicitThrowEvent | ThrowEvent | |
DataState | BaseElement | name(String), |
ItemAwareElement | BaseElement | itemSubjectRef(ItemDefinition), dataState(DataState), |
DataAssociation | BaseElement | sourceRef(ItemAwareElement), targetRef(ItemAwareElement), transformation(FormalExpression), assignment(Assignment), |
DataInput | ItemAwareElement | name(String), isCollection(Boolean), inputSetRef(InputSet), inputSetWithOptional(InputSet), inputSetWithWhileExecuting(InputSet), |
DataOutput | ItemAwareElement | name(String), isCollection(Boolean), outputSetRef(OutputSet), outputSetWithOptional(OutputSet), outputSetWithWhileExecuting(OutputSet), |
InputSet | BaseElement | name(String), dataInputRefs(DataInput), optionalInputRefs(DataInput), whileExecutingInputRefs(DataInput), outputSetRefs(OutputSet), |
OutputSet | BaseElement | dataOutputRefs(DataOutput), name(String), inputSetRefs(InputSet), optionalOutputRefs(DataOutput), whileExecutingOutputRefs(DataOutput), |
Property | ItemAwareElement | name(String), |
DataInputAssociation | DataAssociation | |
DataOutputAssociation | DataAssociation | |
InputOutputSpecification | BaseElement | dataInputs(DataInput), dataOutputs(DataOutput), inputSets(InputSet), outputSets(OutputSet), |
DataObject | FlowElement,ItemAwareElement | isCollection(Boolean), |
InputOutputBinding | inputDataRef(InputSet), outputDataRef(OutputSet), operationRef(Operation), | |
Assignment | BaseElement | from(Expression), to(Expression), |
DataStore | RootElement,ItemAwareElement | name(String), capacity(Integer), isUnlimited(Boolean), |
DataStoreReference | ItemAwareElement,FlowElement | dataStoreRef(DataStore), |
DataObjectReference | ItemAwareElement,FlowElement | dataObjectRef(DataObject), |
ConversationLink | BaseElement | sourceRef(InteractionNode), targetRef(InteractionNode), name(String), |
ConversationAssociation | BaseElement | innerConversationNodeRef(ConversationNode), outerConversationNodeRef(ConversationNode), |
CallConversation | ConversationNode | calledCollaborationRef(Collaboration), participantAssociations(ParticipantAssociation), |
Conversation | ConversationNode | |
SubConversation | ConversationNode | conversationNodes(ConversationNode), |
ConversationNode | InteractionNode,BaseElement | name(String), participantRef(Participant), messageFlowRefs(MessageFlow), correlationKeys(CorrelationKey), |
GlobalConversation | Collaboration | |
PartnerEntity | RootElement | name(String), participantRef(Participant), |
PartnerRole | RootElement | name(String), participantRef(Participant), |
CorrelationProperty | RootElement | correlationPropertyRetrievalExpression(CorrelationPropertyRetrievalExpression), name(String), type(ItemDefinition), |
Error | RootElement | structureRef(ItemDefinition), name(String), errorCode(String), |
CorrelationKey | BaseElement | correlationPropertyRef(CorrelationProperty), name(String), |
Expression | BaseElement | body(String), |
FormalExpression | Expression | language(String), evaluatesToTypeRef(ItemDefinition), |
Message | RootElement | name(String), itemRef(ItemDefinition), |
ItemDefinition | RootElement | itemKind(ItemKind), structureRef(String), isCollection(Boolean), import(Import), |
FlowElement | BaseElement | name(String), auditing(Auditing), monitoring(Monitoring), categoryValueRef(CategoryValue), |
SequenceFlow | FlowElement | isImmediate(Boolean), conditionExpression(Expression), sourceRef(FlowNode), targetRef(FlowNode), |
FlowElementsContainer | BaseElement | laneSets(LaneSet), flowElements(FlowElement), |
CallableElement | RootElement | name(String), ioSpecification(InputOutputSpecification), supportedInterfaceRef(Interface), ioBinding(InputOutputBinding), |
FlowNode | FlowElement | incoming(SequenceFlow), outgoing(SequenceFlow), lanes(Lane), |
CorrelationPropertyRetrievalExpression | BaseElement | messagePath(FormalExpression), messageRef(Message), |
CorrelationPropertyBinding | BaseElement | dataPath(FormalExpression), correlationPropertyRef(CorrelationProperty), |
Resource | RootElement | name(String), resourceParameters(ResourceParameter), |
ResourceParameter | BaseElement | name(String), isRequired(Boolean), type(ItemDefinition), |
CorrelationSubscription | BaseElement | correlationKeyRef(CorrelationKey), correlationPropertyBinding(CorrelationPropertyBinding), |
MessageFlow | BaseElement | name(String), sourceRef(InteractionNode), targetRef(InteractionNode), messageRef(Message), |
MessageFlowAssociation | BaseElement | innerMessageFlowRef(MessageFlow), outerMessageFlowRef(MessageFlow), |
InteractionNode | incomingConversationLinks(ConversationLink), outgoingConversationLinks(ConversationLink), | |
Participant | InteractionNode,BaseElement | name(String), interfaceRef(Interface), participantMultiplicity(ParticipantMultiplicity), endPointRefs(EndPoint), processRef(Process), |
ParticipantAssociation | BaseElement | innerParticipantRef(Participant), outerParticipantRef(Participant), |
ParticipantMultiplicity | BaseElement | minimum(Integer), maximum(Integer), |
Collaboration | RootElement | name(String), isClosed(Boolean), participants(Participant), messageFlows(MessageFlow), artifacts(Artifact), conversations(ConversationNode), conversationAssociations(ConversationAssociation), participantAssociations(ParticipantAssociation), messageFlowAssociations(MessageFlowAssociation), correlationKeys(CorrelationKey), choreographyRef(Choreography), conversationLinks(ConversationLink), |
ChoreographyActivity | FlowNode | participantRef(Participant), initiatingParticipantRef(Participant), correlationKeys(CorrelationKey), loopType(ChoreographyLoopType), |
CallChoreography | ChoreographyActivity | calledChoreographyRef(Choreography), participantAssociations(ParticipantAssociation), |
SubChoreography | ChoreographyActivity,FlowElementsContainer | artifacts(Artifact), |
ChoreographyTask | ChoreographyActivity | messageFlowRef(MessageFlow), |
Choreography | Collaboration,FlowElementsContainer | |
GlobalChoreographyTask | Choreography | initiatingParticipantRef(Participant), |
TextAnnotation | Artifact | text(String), textFormat(String), |
Group | Artifact | categoryValueRef(CategoryValue), |
Association | Artifact | associationDirection(AssociationDirection), sourceRef(BaseElement), targetRef(BaseElement), |
Category | RootElement | categoryValue(CategoryValue), name(String), |
Artifact | BaseElement | |
CategoryValue | BaseElement | categorizedFlowElements(FlowElement), value(String), |
Activity | FlowNode | isForCompensation(Boolean), default(SequenceFlow), ioSpecification(InputOutputSpecification), boundaryEventRefs(BoundaryEvent), properties(Property), dataInputAssociations(DataInputAssociation), dataOutputAssociations(DataOutputAssociation), startQuantity(Integer), resources(ResourceRole), completionQuantity(Integer), loopCharacteristics(LoopCharacteristics), |
ServiceTask | Task | implementation(String), operationRef(Operation), |
SubProcess | Activity,FlowElementsContainer,InteractionNode | triggeredByEvent(Boolean), artifacts(Artifact), |
LoopCharacteristics | BaseElement | |
MultiInstanceLoopCharacteristics | LoopCharacteristics | isSequential(Boolean), behavior(MultiInstanceBehavior), loopCardinality(Expression), loopDataInputRef(ItemAwareElement), loopDataOutputRef(ItemAwareElement), inputDataItem(DataInput), outputDataItem(DataOutput), complexBehaviorDefinition(ComplexBehaviorDefinition), completionCondition(Expression), oneBehaviorEventRef(EventDefinition), noneBehaviorEventRef(EventDefinition), |
StandardLoopCharacteristics | LoopCharacteristics | testBefore(Boolean), loopCondition(Expression), loopMaximum(Integer), |
CallActivity | Activity | calledElement(String), |
Task | Activity,InteractionNode | |
SendTask | Task | implementation(String), operationRef(Operation), messageRef(Message), |
ReceiveTask | Task | implementation(String), instantiate(Boolean), operationRef(Operation), messageRef(Message), |
ScriptTask | Task | scriptFormat(String), script(String), |
BusinessRuleTask | Task | implementation(String), |
AdHocSubProcess | SubProcess | completionCondition(Expression), ordering(AdHocOrdering), cancelRemainingInstances(Boolean), |
Transaction | SubProcess | protocol(String), method(String), |
GlobalScriptTask | GlobalTask | scriptLanguage(String), script(String), |
GlobalBusinessRuleTask | GlobalTask | implementation(String), |
ComplexBehaviorDefinition | BaseElement | condition(FormalExpression), event(ImplicitThrowEvent), |
ResourceRole | BaseElement | resourceRef(Resource), resourceParameterBindings(ResourceParameterBinding), resourceAssignmentExpression(ResourceAssignmentExpression), name(String), |
ResourceParameterBinding | BaseElement | expression(Expression), parameterRef(ResourceParameter), |
ResourceAssignmentExpression | BaseElement | expression(Expression), |
Import | importType(String), location(String), namespace(String), | |
Definitions | BaseElement | name(String), targetNamespace(String), expressionLanguage(String), typeLanguage(String), imports(Import), extensions(Extension), rootElements(RootElement), diagrams(bpmndi:BPMNDiagram), exporter(String), relationships(Relationship), exporterVersion(String), |
camunda拓展元素
类型名称 | 拓展父类 | 父元素 | 属性 |
---|---|---|---|
InOutBinding | Element | camunda:source(String), camunda:sourceExpression(String), camunda:target(String), camunda:businessKey(String), camunda:local(Boolean), camunda:variables(String), | |
In | InOutBinding | ||
Out | InOutBinding | ||
AsyncCapable | bpmn:Activity, bpmn:Gateway, bpmn:Event | camunda:async(Boolean), camunda:asyncBefore(Boolean), camunda:asyncAfter(Boolean), camunda:exclusive(Boolean), | |
JobPriorized | bpmn:Process, camunda:AsyncCapable | camunda:jobPriority(String), | |
SignalEventDefinition | bpmn:SignalEventDefinition | camunda:async(Boolean), | |
ErrorEventDefinition | bpmn:ErrorEventDefinition | camunda:errorCodeVariable(String), camunda:errorMessageVariable(String), | |
Error | bpmn:Error | camunda:errorMessage(String), | |
PotentialStarter | Element | camunda:resourceAssignmentExpression(bpmn:ResourceAssignmentExpression), | |
FormSupported | bpmn:StartEvent, bpmn:UserTask | camunda:formHandlerClass(String), camunda:formKey(String), | |
TemplateSupported | bpmn:Process, bpmn:FlowElement | camunda:modelerTemplate(String), | |
Initiator | bpmn:StartEvent | camunda:initiator(String), | |
ScriptTask | bpmn:ScriptTask | camunda:resultVariable(String), camunda:resource(String), | |
Process | bpmn:Process | camunda:candidateStarterGroups(String), camunda:candidateStarterUsers(String), camunda:versionTag(String), camunda:historyTimeToLive(String), camunda:isStartableInTasklist(Boolean), | |
EscalationEventDefinition | bpmn:EscalationEventDefinition | camunda:escalationCodeVariable(String), | |
FormalExpression | bpmn:FormalExpression | camunda:resource(String), | |
Assignable | bpmn:UserTask | camunda:assignee(String), camunda:candidateUsers(String), camunda:candidateGroups(String), camunda:dueDate(String), camunda:followUpDate(String), camunda:priority(String), | |
CallActivity | bpmn:CallActivity | camunda:calledElementBinding(String), camunda:calledElementVersion(String), camunda:calledElementVersionTag(String), camunda:calledElementTenantId(String), camunda:caseRef(String), camunda:caseBinding(String), camunda:caseVersion(String), camunda:caseTenantId(String), camunda:variableMappingClass(String), camunda:variableMappingDelegateExpression(String), | |
ServiceTaskLike | bpmn:ServiceTask, bpmn:BusinessRuleTask, bpmn:SendTask, bpmn:MessageEventDefinition | camunda:expression(String), camunda:class(String), camunda:delegateExpression(String), camunda:resultVariable(String), camunda:test(String), | |
DmnCapable | bpmn:BusinessRuleTask | camunda:decisionRef(String), camunda:decisionRefBinding(String), camunda:decisionRefVersion(String), camunda:mapDecisionResult(String), camunda:decisionRefTenantId(String), | |
ExternalCapable | camunda:ServiceTaskLike | camunda:type(String), camunda:topic(String), | |
TaskPriorized | bpmn:Process, camunda:ExternalCapable | camunda:taskPriority(String), | |
Properties | Element | camunda:values(camunda:Property), | |
Property | Element | camunda:id(String), camunda:name(String), camunda:value(String), | |
Connector | Element | camunda:inputOutput(camunda:InputOutput), camunda:connectorId(String), | |
InputOutput | Element | camunda:inputOutput(camunda:InputOutput), camunda:connectorId(String), camunda:inputParameters(camunda:InputParameter), camunda:outputParameters(camunda:OutputParameter), | |
InputOutputParameter | camunda:name(String), camunda:value(String), camunda:definition(camunda:InputOutputParameterDefinition), | ||
InputOutputParameterDefinition | |||
List | InputOutputParameterDefinition | camunda:items(camunda:InputOutputParameterDefinition), | |
Map | InputOutputParameterDefinition | camunda:entries(camunda:Entry), | |
Entry | camunda:key(String), camunda:value(String), camunda:definition(camunda:InputOutputParameterDefinition), | ||
Value | InputOutputParameterDefinition | camunda:id(String), camunda:name(String), camunda:value(String), | |
Script | InputOutputParameterDefinition | camunda:scriptFormat(String), camunda:resource(String), camunda:value(String), | |
Field | Element | camunda:name(String), camunda:expression(String), camunda:stringValue(String), camunda:string(String), | |
InputParameter | InputOutputParameter | ||
OutputParameter | InputOutputParameter | ||
Collectable | bpmn:MultiInstanceLoopCharacteristics | camunda:AsyncCapable | camunda:collection(String), camunda:elementVariable(String), |
FailedJobRetryTimeCycle | Element | camunda:body(String), | |
ExecutionListener | Element | camunda:expression(String), camunda:class(String), camunda:delegateExpression(String), camunda:event(String), camunda:script(camunda:Script), camunda:fields(camunda:Field), | |
TaskListener | Element | camunda:expression(String), camunda:class(String), camunda:delegateExpression(String), camunda:event(String), camunda:script(camunda:Script), camunda:fields(camunda:Field), | |
FormProperty | Element | camunda:id(String), camunda:name(String), camunda:type(String), camunda:required(String), camunda:readable(String), camunda:writable(String), camunda:variable(String), camunda:expression(String), camunda:datePattern(String), camunda:default(String), camunda:values(camunda:Value), | |
FormData | Element | camunda:fields(camunda:FormField), camunda:businessKey(String), | |
FormField | Element | camunda:id(String), camunda:label(String), camunda:type(String), camunda:datePattern(String), camunda:defaultValue(String), camunda:properties(camunda:Properties), camunda:validation(camunda:Validation), camunda:values(camunda:Value), | |
Validation | Element | camunda:constraints(camunda:Constraint), | |
Constraint | Element | camunda:name(String), camunda:config(String), | |
ConditionalEventDefinition | bpmn:ConditionalEventDefinition | camunda:variableName(String), camunda:variableEvent(String), |
3.2.2、读取元素属性
// 获得元素注册器
let elementRegistry = viewer.get('elementRegistry');
// 使用元素注册器获得特定id的元素
let sequenceFlowEmenent = elementRegistry.get('SequenceFlow_1');
// 获取元素的businessObject对象,使用该对象获取元素属性
let sbo = sequenceFlowEmenent.businessObject;
console.log(sbo.name);
3.2.3、编辑元素属性
bpmn定义了几十个默认的元素类型,他们各自有对应的属性配置。使用businessObject可以对这些属性进行赋值。
// 接 3.2.1
// 使用moddle服务创建一个FormalExpression类型的元素,这是一个表达式属性元素
let moddle = viewer.get('moddle');
let newCondition = moddle.create('bpmn:FormalExpression', {
body: '${ value > 100 }'
});
// 属性赋值,conditionExpression是SequenceFlow类型元素(连接线)的一个属性
sbo.conditionExpression = newCondition;
3.3、自定义元素
示例项目:https://github.com/bpmn-io/bpmn-js-nyan
nyan是一个自定义图形元素的示例总集,完成了一个自定义元素的典型实现。主要组成部分包括:
- color-picker – 元素背景色设置服务,用于添加自定义上下文面板图标,并在点击后改变节点的颜色。
- draw – 自定义图形元素渲染器,用于绘制元素显示效果。
- palette – 自定义工具栏,用于在工具栏产生特殊的元素图标。
该项目实现了将一个ServiceTask任务节点的图标替换成一个git卡通猫图片。以下分别就上面的三个核心组成部分进行详细介绍。
3.3.1、color-picker
color-picker注册了两个服务模块:colorPicker和coloredRenderer。
-
colorPicker – colorPicker 做了两件事:向上下文面板添加自定义操作项,向命令栈注册自定义命令。通过这两件事colorPicker 实现了通过点击上下文面板中的自定义操作项改变元素的color属性的值。具体实现如下:
- 1、colorPicker 使用contextPad.registerProvider向上下文面板注册自己。
- 2、为了实现改变元素颜色目的,colorPicker 使用commandStack注册了自定义命令【shape.updateColor】,使用这个命令执行改变元素颜色特征。
// commandStack命令的注册 commandStack.registerHandler('shape.updateColor', UpdateColorHandler); // 命令函数可以传入一个context对象作为参数 function UpdateColorHandler(){ // 命令函数中有两个方法,分别是execute和revert,表示执行和回退 this.execute = function(context) { const { element, color } = context; // 缓存原来值,用于回退 context.oldColor = element.color; // 赋予元素颜色新值 element.color = color; return element; } this.revert = function(context) { // 恢复上一个值 context.element.color = context.oldColor; return context.element; } }
- 3、定义getContextPadEntries函数,注册一个叫做changeColor的上下文图标。注册该图标的点击事件监听,在点击事件中触发第2步中的自定义命令。
this.getContextPadEntries = function(element) { if (is(element, 'bpmn:Event')) { return { 'changeColor': { group: 'edit', className: 'icon-red', title: 'Change element color', action: { click: changeColor } } }; } }; function changeColor(event, element) { var color = window.prompt('type a color code'); commandStack.execute('shape.updateColor', { element: element, color: color }); }
**注意: **以上操作只是改变了元素的color特征值,并不能改变元素颜色。但是自定义命令的触发却能引发页面元素的重新渲染。
-
ColoredRenderer – 在其drawShape中读取元素中存储的color特征值,使用该值改变元素svg对象的fill值,从而实现颜色渲染。
3.3.2、draw – NyanRender
NyanRender和ColoredRenderer 两个模块在类型上是一样的,都是用于自定义渲染图形元素,对比两个模块可知,自定义渲染器必须要在构造函数中实现两个方法:
- drawShape:使用svg自定义图形形状,因此可以直接拿一个svg图标作为形状使用(svg也支持插入普通图片,如gif的base64字符串)。
- drawShape返回一个tiny-svg插件的提供的create函数创建的svg对象。
- canRender:判断那种类型的元素需要使用该渲染器,一般通过ModelUtil提供的is函数即可。
3.3.3、palette – NyanPaletteProvider
NyanPaletteProvider用于在工具栏创建自定义元素图标,该类型模块的的核心函数是getPaletteEntries,与colorPicker 用到的getContextPadEntries方法不同之处在于,这是个原型函数,而getContextPadEntries却是属性函数,这可能是因为工具栏只有一个,而上下文面板有多个的原因。
- NyanPaletteProvider需要使用palette.registerProvider(this)方式注册到工具栏中。
- getPaletteEntries 函数返回一个对象,对象的一级属性是表示要添加到工具栏的子对象,也就是可以一次性添加很多图标,这个一级对象有如下属性:
- group :所属工具栏分组,activity是工具栏的默认分组
- title:工具标题
- class-name:字体图标类名
- imageUrl:图标图片路径,是个base64字符串
- action:事件注册器,可以注册dragstart事件监听,使用该事件在画布上创建一个图形元素。
// dragstart 事件触发元素创建
function dragstartAction(event) {
// 使用elementFactory创建一个ServiceTask元素,该元素首先需要是bpmn配置json中存在的。
let shape = elementFactory.create('shape', {
type: 'bpmn:ServiceTask'
});
// 使用create对象创建。create和elementFactory都是bpmn的内置对象,切都已通过NyanPaletteProvider的构造函数注入进来。
create.start(event, shape);
}
更多推荐
所有评论(0)