Skip to main content

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.

note

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);
}
});