linkTools
A link tool is a view that renders a certain type of control elements on top of the LinkView it is attached to; for example the Vertices tool creates an interactive handle above every vertex (these handles then allow the user to move and/or delete each vertex). Link tools all inherit from the joint.dia.ToolView
class. A collection of tools is added to a ToolsView; a tools view is then added to the linkView with the linkView.addTools()
function.
The JointJS library comes with a collection of pre-made link tool definitions in the joint.linkTools
namespace:
Vertices
- adds handles above link verticesSegments
- adds handles above link segmentsSourceArrowhead
- adds a handle above link sourceTargetArrowhead
- adds a handle above link targetSourceAnchor
- adds a handle above link source anchorTargetAnchor
- adds a handle above link target anchorBoundary
- shows link bboxRemove
- adds an interactive remove buttonControl
- adds a button to change link attributesRotateLabel
- adds a button to rotate link labels
To create a new link tool, we call its constructor. Example:
var verticesTool = new joint.linkTools.Vertices({
snapRadius: 10
});
In addition, the joint.linkTools
namespace contains a customizable button class:
Button
- adds a customizable button
Example:
var infoTool = new joint.linkTools.Button({
markup: [{
tagName: 'circle',
selector: 'button',
attributes: {
'r': 7,
'fill': '#001DFF',
'cursor': 'pointer'
}
}, {
tagName: 'path',
selector: 'icon',
attributes: {
'd': 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
'fill': 'none',
'stroke': '#FFFFFF',
'stroke-width': 2,
'pointer-events': 'none'
}
}],
distance: 60,
offset: 0,
action: function(evt) {
alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
}
});
All of the built-in link tools accept the following optional argument, in addition to their own arguments:
focusOpacity | number | What should be the opacity of the tool when it is focused (e.g. with the toolView.focus function)? Default is undefined , meaning that the tool's opacity is kept unchanged. |
---|
Example:
var verticesTool = new joint.linkTools.Vertices({
focusOpacity: 0.5
});
Classesβ
Boundaryβ
The Boundary
link tool renders a rectangular border to show the bounding box of the link. It accepts a few additional arguments, which can be passed as an object to the link tool constructor:
padding | number|object | This option determines whether the boundary area should be visually inflated and if so, by how much. Default is 10 ({ left: 10, top: 10, right: 10, bottom: 10 } ). |
---|---|---|
useModelGeometry | boolean | If this option is set to true , the position of the boundary is calculated based on the dimensions of the link model. |
Example:
var boundaryTool = new joint.linkTools.Boundary({
focusOpacity: 0.5,
padding: 20,
useModelGeometry: true
});
Buttonβ
The Button
link tool allows you to have a custom button rendered at a given position along the link. It accepts five additional arguments, which can be passed as an object to the link tool constructor:
distance | number | Distance at which the button should be placed. Negative numbers are accepted; then the distance is counted from the end of the link. Default is 0 . |
---|---|---|
string | Percentage strings (e.g. '40%' ) are also accepted. | |
function | The callback function is expected to have the signature
| |
rotate | boolean | Should the button rotate according to the slope of the link at the position specified by distance ? Default is false . |
offset | number | Relative offset of the button from the link. Positive numbers mean that the button should be offset to the right of the link (relative to the direction from source to target); negative numbers mean that the button should be offset to the left of the link (relative to the direction from source to target). Default is 0 . |
action | function | What should happen when the user clicks the button? Default is undefined (no interaction).The callback function is expected to have the signature function(evt, linkView, buttonView) where evt is a DOM event. The related link view is available inside the function as this . The link model is available as this.model . |
markup | JSONMarkup | The markup of the button, provided in the JointJS JSON format. Default is undefined (no content). |
scale | number | Scale the button up or down on a 2D plane. The default is 1 . |
Example of a useful custom info button:
var infoButton = new joint.linkTools.Button({
focusOpacity: 0.5,
distance: 60,
action: function(evt) {
alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
},
markup: [{
tagName: 'circle',
selector: 'button',
attributes: {
'r': 7,
'fill': '#001DFF',
'cursor': 'pointer'
}
}, {
tagName: 'path',
selector: 'icon',
attributes: {
'd': 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
'fill': 'none',
'stroke': '#FFFFFF',
'stroke-width': 2,
'pointer-events': 'none'
}
}]
});
The linkTools.Button
class can also be extended, to create a reusable custom button type. Then, a new instance of the custom button type can be obtained by calling its constructor:
var InfoButton = joint.linkTools.Button.extend({
name: 'info-button',
options: {
focusOpacity: 0.5,
distance: 60,
action: function(evt) {
alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
},
markup: [{
tagName: 'circle',
selector: 'button',
attributes: {
'r': 7,
'fill': '#001DFF',
'cursor': 'pointer'
}
}, {
tagName: 'path',
selector: 'icon',
attributes: {
'd': 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
'fill': 'none',
'stroke': '#FFFFFF',
'stroke-width': 2,
'pointer-events': 'none'
}
}]
}
});
var infoButton = new InfoButton();
Connectβ
The Connect
tool allows the user to create links in a drag & drop fashion. The tool extends the Button tool and accepts additional arguments, which can be passed as an object to the connect tool constructor:
magnet | string SVGElement (view: dia.ElementView) => SVGElement | Choose the source magnet of the element view which the new link should be connected to.
The callback function is expected to have the signature |
---|
Example:
const connectButton = new joint.linkTools.Connect({
rotate: true,
distance: -20,
offset: 20,
magnet: 'body'
});
HoverConnectβ
The HoverConnect
tool allows the user to create links from other links in a drag & drop fashion. The tool extends the Connect tool. The difference is that the button appears along the invisible track path (in the shape of a linkView) at the point where the user moves the mouse over the track. It accepts additional arguments, which can be passed as an object to the hover connect tool constructor:
trackWidth | number | The thickness of the track path. The default is 15 . |
---|
Example:
const hoverButton = new joint.linkTools.HoverConnect({
magnet: 'body',
trackWidth: 10
});
Removeβ
The Remove
link tool renders a remove button at a given position along the link. It accepts five additional arguments, which can be passed as an object to the link tool constructor:
distance | number | Distance at which the button should be placed. Negative numbers are accepted; then the distance is counted from the end of the link. Default is |
---|---|---|
string | Percentage strings (e.g. '40%' ) are also accepted. | |
rotate | boolean | Should the button rotate according to the slope of the link at the position specified by distance ? Default is false . |
offset | number | Relative offset of the button from the link. Positive numbers mean that the button should be offset to the right of the link (relative to the
direction from source to target); negative numbers mean that the button should be offset to the left of the link (relative to the direction from
source to target). Default is |
action | function | What should happen when the user clicks the remove button? Default:
The callback function is expected to have the signature |
markup | JSONMarkup | The markup of the button, provided in the JointJS JSON format. Default:
|
scale | number | Scale the button up or down on a 2D plane. The default is 1 . |
Example:
var removeButton = new joint.linkTools.Remove({
focusOpacity: 0.5,
rotate: true,
distance: -20,
offset: 20
});
Segmentsβ
The Segments
link tool renders handles above all segments of the link (as determined by the link connector). It accepts four additional arguments, which can be passed as an object to the link tool constructor:
redundancyRemoval | boolean | If the user arranges two (or more) segments so that they lie on a single line, should the middle one(s) be considered redundant and removed? Default is true . Note that this setting is not applied until the user actually moves one of the segments in question; this means that segments can still be arranged in this redundantfashion, using the link.vertices function, for example. |
---|---|---|
segmentLengthThreshold | number | The minimum segment length for which to display a segment handle (to prevent the handle from overflowing its segment). Default is 40 . |
snapRadius | number | While the user is moving the segment, from how far away should the segment snap in order to arrange itself in line with another segment? Default is 10 . |
snapHandle | number | If the snapRadius option is set to true and the segment is snapped in place while the user moves the segment handle, should the handle follow the user pointer or should the handle stay snapped with the segment until it un-snaps? Default is true , meaning that the handle snaps with the segment. |
stopPropagation | boolean | Should be events stopped from propagating to the paper? Default is true . |
handleClass | mvc.View | The view for the segment handle. By default it uses linkTools.Segments.SegmentHandle class. |
scale | number | Scale the segment handles up or down on a 2D plane. The default is 1 . |
The tool is meant to be used with normal router only. It does not work with e.g. orthogonal router. It throws the "Segments: incompatible router in use" error if used with any other router.
Example:
var segmentsTool = new joint.linkTools.Segments({
focusOpacity: 0.5,
redundancyRemoval: false,
segmentLengthThreshold: 50,
snapHandle: false,
snapRadius: 10
});
SourceAnchorβ
The SourceAnchor
link tool renders a handle above the source anchor of the link (as determined by the anchor function applied on link source). It accepts several additional arguments, which can be passed as an object to the link tool constructor:
redundancyRemoval | boolean | If the user moves the anchor so that it lies on a single line with two (or more) vertices, should the middle one(s) be considered redundant and removed? Default is true . Note that this setting is not applied until the user actually moves the anchor; this means that the anchor and vertices can still be arranged in this redundantfashion, using the link.vertices function, for example. | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
restrictArea | boolean | Should the user only be allowed to move the anchor in a restricted area (the area of the bounding box of the source magnet)? Default is true . | ||||||||||||||||||
areaPadding | number | If the restrictArea option is set to true , the user can only move the anchor in a restricted area (the area of the bounding box of the source magnet). JointJS shows this restriction by drawing a boundary around that area. This option determines whether this boundary area should be visually inflated and if so, by how much. Default is 10 . Note that this is a purely cosmetic setting; regardless of the provided value, the movement stays restricted to the original uninflated bounding box. | ||||||||||||||||||
snapRadius | number | While the user is moving the anchor, from how far away should the segment snap in order to arrange itself in line with the anchor reference? Default is 10 . (For link source, the anchor reference is the first vertex. If there are no vertices, it is the target anchor.) | ||||||||||||||||||
resetAnchor | boolean | object | When the user double clicks the anchor tool, the following action should be performed:
| ||||||||||||||||||
snap | function | What snap function should be applied when the user moves the anchor? Default is a simple function that emulates the snapping behavior of Vertices and Segments link tools: If the value of one of the user pointer coordinates is within snapRadius of the value of a coordinate of the anchor reference, snap to the reference value. (For link source, the anchor reference is the first vertex. If there are no vertices, it is the target anchor.)The callback function must return the anchor as a g.Point and have the signature function(coords, endView, endMagnet, endType, linkView, toolView) :
| ||||||||||||||||||
scale | number | Scale the anchor element up or down on a 2D plane. The default is 1 . |
Example:
var sourceAnchorTool = new joint.linkTools.SourceAnchor({
focusOpacity: 0.5,
redundancyRemoval: false,
restrictArea: false,
snapRadius: 20
});
An example of a useful custom snap
function is provided below. It snaps the anchor to the center of the closest side of the restricted area.
var snapAnchor = function(coords, endView, endMagnet) {
// remove rotation of the restricted area
var bbox = endView.getNodeUnrotatedBBox(endMagnet);
var angle = endView.model.angle();
var origin = endView.model.getBBox().center();
coords.rotate(origin, angle);
// identify the side nearest to pointer coords
var anchor;
var side = bbox.sideNearestToPoint(coords);
switch (side) {
case 'left': anchor = bbox.leftMiddle(); break;
case 'right': anchor = bbox.rightMiddle(); break;
case 'top': anchor = bbox.topMiddle(); break;
case 'bottom': anchor = bbox.bottomMiddle(); break;
}
// rotate the anchor according to original rotation of restricted area
return anchor.rotate(origin, -angle);
};
var sourceAnchorTool = new joint.linkTools.SourceAnchor({
snap: snapAnchor;
});
If the user moves the anchor away from its original position, the anchor position may be reset by double-clicking the anchor handle.
SourceArrowheadβ
The SourceArrowhead
link tool renders an arrow-like handle above the source connection point of the link (as determined by the connectionPoint function applied on link source). It accepts a few additional arguments, which can be passed as an object to the link tool constructor:
scale | number | Scale the arrowhead element up or down on a 2D plane. The default is 1 . |
---|
Example:
var sourceArrowheadTool = new joint.linkTools.SourceArrowhead({
focusOpacity: 0.5
});
TargetAnchorβ
The TargetAnchor
link tool renders a handle above the target anchor of the link (as determined by the anchor function applied on link target). It accepts several additional arguments, which can be passed as an object to the link tool constructor:
redundancyRemoval | boolean | If the user moves the anchor so that it lies on a single line with two (or more) vertices, should the middle one(s) be considered redundant and removed? Default is true . Note that this setting is not applied until the user actually moves the anchor; this means that the anchor and vertices can still be arranged in this redundantfashion, using the link.vertices function, for example. | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
restrictArea | boolean | Should the user only be allowed to move the anchor in a restricted area (the area of the bounding box of the target magnet)? Default is true . | ||||||||||||||||||
areaPadding | number | If the restrictArea option is set to true , the user can only move the anchor in a restricted area (the area of the bounding box of the target magnet). JointJS shows this restriction by drawing a boundary around that area. This option determines whether this boundary area should be visually inflated and if so, by how much. Default is 10 . Note that this is a purely cosmetic setting; regardless of the provided value, the movement stays restricted to the original uninflated bounding box. | ||||||||||||||||||
snapRadius | number | While the user is moving the anchor, from how far away should the segment snap in order to arrange itself in line with the anchor reference? Default is 10 . (For link target, the anchor reference is the last vertex. If there are no vertices, it is the source anchor.) | ||||||||||||||||||
resetAnchor | boolean | object | When the user double clicks the anchor tool, the following action should be performed:
| ||||||||||||||||||
snap | function | What snap function should be applied when the user moves the anchor? Default is a simple function that emulates the snapping behavior of Vertices and Segments link tools: If the value of one of the user pointer coordinates is within snapRadius of the value of a coordinate of the anchor reference, snap to the reference value. (For link target, the anchor reference is the last vertex. If there are no vertices, it is the source anchor.)The callback function must return the anchor as a g.Point and have the signature function(coords, endView, endMagnet) :
| ||||||||||||||||||
scale | number | Scale the anchor element up or down on a 2D plane. The default is 1 . |
Example:
var targetAnchorTool = new joint.linkTools.TargetAnchor({
focusOpacity: 0.5,
redundancyRemoval: false,
restrictArea: false,
snapRadius: 20
});
An example of a useful custom snap
function is provided below. It snaps the anchor to the center of the closest side of the restricted area.
var snapAnchor = function(coords, endView, endMagnet) {
// remove rotation of the restricted area
var bbox = endView.getNodeUnrotatedBBox(endMagnet);
var angle = endView.model.angle();
var origin = endView.model.getBBox().center();
coords.rotate(origin, angle);
// identify the side nearest to pointer coords
var anchor;
var side = bbox.sideNearestToPoint(coords);
switch (side) {
case 'left': anchor = bbox.leftMiddle(); break;
case 'right': anchor = bbox.rightMiddle(); break;
case 'top': anchor = bbox.topMiddle(); break;
case 'bottom': anchor = bbox.bottomMiddle(); break;
}
// rotate the anchor according to original rotation of restricted area
return anchor.rotate(origin, -angle);
};
var targetAnchorTool = new joint.linkTools.TargetAnchor({
snap: snapAnchor;
});
If the user moves the anchor away from its original position, the anchor position may be reset by double-clicking the anchor handle.
TargetArrowheadβ
The TargetArrowhead
link tool renders an arrow-like handle above the target connection point of the link (as determined by the connectionPoint function applied on link target). It accepts a few additional arguments, which can be passed as an object to the link tool constructor:
scale | number | Scale the arrowhead element up or down on a 2D plane. The default is 1 . |
---|
Example:
var targetArrowheadTool = new joint.linkTools.TargetArrowhead({
focusOpacity: 0.5
});
Verticesβ
The Vertices
link tool renders handles above all vertices of the link. It accepts three additional arguments, which can be passed as an object to the link tool constructor:
redundancyRemoval | boolean | If the user arranges three (or more) vertices so that they lie on a single line, should the middle one(s) be considered redundant and removed? Default is true . Note that this setting is not applied until the user actually moves one of the vertices in question; this means that vertices can still be arranged in this redundantfashion, using of the link.vertices function, for example. | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
snapRadius | number | While the user is moving the vertex, from how far away should the vertex snap in order to arrange itself perpendicularly to another vertex? Default is 20 . | ||||||||
vertexAdding | boolean | Can the user add new vertices (by clicking a segment of the link)?
| ||||||||
vertexMoving | boolean | Can the user move vertices (by dragging them)? Default is true . | ||||||||
vertexRemoving | boolean | Can the user remove vertices (by double clicking them)? Default is true . | ||||||||
stopPropagation | boolean | Should be events stopped from propagating to the paper? Default is true . | ||||||||
handleClass | mvc.View | The view for the vertex handle. By default it uses linkTools.Vertices.VertexHandle class. | ||||||||
scale | number | Scale the vertices handles up or down on a 2D plane. The default is 1 . |
Example:
var verticesTool = new joint.linkTools.Vertices({
focusOpacity: 0.5,
redundancyRemoval: false,
snapRadius: 10,
vertexAdding: false,
});
VertexAddingOptionsβ
Option | Type | Description |
---|---|---|
interactiveLinkNode | string | A selector of an existing link node, e.g. "wrapper" . When the node is interacted with, a vertex is created. |
The default is true
.
const verticesTool = new linkTools.Vertices({
// The link node referenced by the selector "outline"
// will create a vertex when interacted with.
vertexAdding: { interactiveLinkNode: 'outline' }
}),
Controlβ
The Control
link tool is an abstract class which allows you to build tools to control the look or shape of a link by simply dragging a UI handle. It accepts a few additional arguments, which can be passed as an object to the link tool constructor:
selector | string | null | The link selector pointing to a link subnode, which the tool draws a frame around during dragging. If null provided, no frame will be shown. |
---|---|---|
padding | number | The padding between the area and the bounding box of the node designated by selector . |
handleAttributes | function | An object with SVG attributes to be applied to the tool's handle. |
scale | number | Scale the button up or down on a 2D plane. The default is 1 . |
namespace Control {
interface Options extends dia.ToolView.Options {
selector?: string;
padding?: number;
handleAttributes?: Partial<attributes.NativeSVGAttributes>
}
}
abstract class Control extends dia.ToolView {
protected getPosition(view: dia.LinkView): dia.Point;
protected setPosition(view: dia.LinkView, coordinates: g.Point, evt: dia.Event): void;
protected resetPosition(view: dia.LinkView, evt: dia.Event): void;
}
getPosition(view: dia.LinkView): dia.Point; | The method should return the position of the handle based on a model value. The position is defined in the graph coordinate system. |
setPosition(view: dia.LinkView, coordinates: g.Point, evt: dia.Event): void; | The method is executed each time the handle is moved. It's supposed to set the new model value derived from the current pointer |
resetPosition(view: dia.LinkView, evt: dia.Event): void; | The method is executed when the handle is double-clicked. It's supposed to reset the model value back to a default. |
See element Control tool for example usage.
RotateLabelβ
The RotateLabel
link tool allows you to rotate the link label by dragging a handle. It extends the Control tool and accepts additional arguments, which can be passed as an object to the link tool constructor:
labelIndex | number | The index of the label in the labels array of the link model. Default is 0 . |
---|---|---|
buttonColor | string | The color of the handle. Default is #333 . |
iconColor | string | The color of the icon. Default is #fff . |
outlineColor | string | The color of the handle outline. Default is #333 . |
If the link has multiple labels, you can specify the index of the label you want to rotate using the labelIndex
option.
If the label with given index does not exist, the rendering of the tool will be posponed until the label is added.