BPMN shapes
JointJS+ provides you with a set of Business Process Model and Notation 2.0 shapes. They are designed to be easily configurable with the Inspector.
The plugin consists of flow shapes (Activities, Events, Gateways), connection objects (Flows), several icons and artifacts (DataObjects, Groups, Annotation). It also covers models introduced in version 2.0: Conversations and Connections.
The BPMN shapes are contained inside shapes.bpmn2
namespace and you can use them as we described earlier.
Basic shapesβ
Here is an example with basic BPMN shapes
Poolsβ
JointJS+ also provides complex Pool shapes to use in your applications.
The BPMN Pool consists of lanes and milestones. let's describe how they work in terms of JointJS shape.
Each lane and milestone group has a unique id that can be used to target those groups or individual elements within groups. Passing string to id
property of a lane or milestone will create an alias to that given group.
Custom id must be unique and the same id cannot be assigned for more than 1 milestone or 1 lane group.
Lane group id starts with a 'lanes' prefix and a combination of numbers that is based on position within an array and nest level (sublanes). Each lane group contains the following elements:
- lane rectangle (prefix
lane
) - header rectangle (prefix
header
, note that header won't be added if label is undefined) - label text (prefix
label
, note that label won't be added if it is undefined)
For example let's consider this lanes structure:
lanes: [
{
label: 'lane' // group id: 'lanes_0', lane id: 'lane_0', header id: 'header_0', label id: 'label_0'
},
{
label: 'lane with sublanes', // group id: 'lanes_1', lane id: 'lane_1', header id: 'header_1', label id: 'label_1'
sublanes: [
{
label: 'sublane 1' // group id: 'lanes_1_0', lane id: 'lane_1_0', header id: 'header_1_0', label id: 'label_1_0'
},
{
label: 'sublane 2' // group id: 'lanes_1_1', lane id: 'lane_1_1', header id: 'header_1_1', label id: 'label_1_1'
}
]
},
// example with custom id
{
id: 'customId',
label: 'lane with custom id', // group id: 'lanes_customId', lane id: 'lane_customId', header id: 'header_customId', label id: 'label_customId'
sublanes: [
{
label: 'sublane 1' // group id: 'lanes_2_0', lane id: 'lane_2_0', header id: 'header_2_0', label id: 'label_2_0'
},
{
id: 'sublaneId',
label: 'sublane 2' // group id: 'lanes_sublaneId', lane id: 'lane_sublaneId', header id: 'header_sublaneId', label id: 'label_sublaneId'
}
]
}
]
Similarly, each milestone group id starts with a 'milestone' prefix. Milestone group contains the following elements:
- header rectangle (prefix
milestoneHeader
) - label text (prefix
milestoneLabel
) - milestone line (prefix
milestoneLine
)
Example milestones structure:
milestones: [
{
label: 'milestone 1' // group id: 'milestone_0', header id: 'milestoneHeader_0', label id: 'milestoneLabel_0', line id: 'milestoneLine_0'
},
{
label: 'milestone 2' // group id: 'milestone_1', header id: 'milestoneHeader_1', label id: 'milestoneLabel_1', line id: 'milestoneLine_1'
},
// example with custom id
{
id: 'customId',
label: 'milestone 3' // group id: 'milestone_customId', header id: 'milestoneHeader_customId', label id: 'milestoneLabel_customId', line id: 'milestoneLine_customId'
}
]
Here is the example of Pool shapes.
SwimlaneBoundary element toolβ
The SwimlaneBoundary
element tool renders a rectangular border to show the bounding box of a bpmn2.Pool
and bpmn2.HeaderedPool
pool lane.
Exampleβ
const boundaryTool = new elementTools.SwimlaneBoundary({
laneId: 'customLaneId',
padding: 20
});
SwimlaneTransform element toolβ
The SwimlaneTransform
element tool allows you to resize lanes in bpmn2.Pool
or bpmn2.HeaderedPool
shape,
from the UI. It renders 4 handles around selected lane which you drag and use to resize lane in particular direction.
Examplesβ
const transformTool = new SwimlaneTransform({
laneId: 'customLaneId',
padding: 8,
minSize: 50,
focusOpacity: 0.5
constraintsPadding: 20,
});
Example with custom constraint points:
graph.on('change:parent', function(element, parentId) {
if (parentId) {
const pool = graph.getCell(parentId);
const [laneId] = pool.getLanesFromPoint(element.getBBox().center());
element.prop('laneId', laneId);
} else {
element.prop('laneId', null);
}
});
const transformTool = new SwimlaneTransform({
laneId: 'customLaneId',
constraintsPadding: 30,
minSizeConstraints: (model, laneId, handleSide) => {
const minPoints = [];
const embedCells = model.getEmbeddedCells();
if (embedCells.length === 0) return;
embedCells.forEach(cell => {
if (cell.prop('laneId') === laneId) {
const cellBBox = cell.getBBox();
minPoints.push(cellBBox.topLeft());
minPoints.push(cellBBox.topRight());
minPoints.push(cellBBox.bottomLeft());
minPoints.push(cellBBox.bottomRight());
}
});
if (handleSide === 'left' || handleSide === 'right') {
const embedsBBox = model.graph.getCellsBBox(embedCells);
// add left most and right most points
minPoints.push(embedsBBox.origin());
minPoints.push(embedsBBox.corner());
}
return minPoints;
},
maxSizeConstraints: (model, laneId) => {
const maxPoints = [];
const embedCells = model.getEmbeddedCells();
if (embedCells.length === 0) return;
embedCells.forEach(cell => {
if (cell.prop('laneId') !== laneId) {
const cellBBox = cell.getBBox();
maxPoints.push(cellBBox.topLeft());
maxPoints.push(cellBBox.topRight());
maxPoints.push(cellBBox.bottomLeft());
maxPoints.push(cellBBox.bottomRight());
}
});
return maxPoints;
}
});
Markers handlingβ
Multiple shapes in BPMN namespace contain different markers. The marker value is stored as a data attribute on the marker icon (SVG path) element. An interaction with the marker icon can be caught and handled on the dia.Paper. In the example bellow the model's marker name is displayed on interaction with the icon.
paper.on('element:marker:pointerdown', (cellView, evt) => {
const markerName = evt.target.dataset.iconType;
if (markerName) {
alert(markerName);
}
});