Skip to main content

Overlays

Overlays are adornments to connections - such things as arrows at the end of a line, or a label, etc. The Toolkit ships with a few types of overlay:

  • Arrow - a configurable arrow that is painted at some point along the connector. You can control the length and width of the Arrow, the 'foldback' point - a point the tail points fold back into, and the direction (allowed values are 1 and -1; 1 is the default and means point in the direction of the connection)
  • Label - a configurable label that is painted at some point along the connector.
  • PlainArrow - an Arrow shaped as a triangle, with no foldback.
  • Diamond - A diamond shaped overlay.
  • Custom - allows you to create the overlay yourself - your overlay may be any DOM element you like.

PlainArrow and Diamond are actually just configured instances of the generic Arrow overlay (see examples).

Configuring overlays

Overlays can be configured in a few different places:

  • As part of the default values in the render params for a surface. Overlays defined here will be applied to every edge in the UI.
  • As part of an edge definition inside a view. Overlays defined inside edge definitions will appear on edges of that specific type (or on edges whose type declares that type as a parent)
  • In a UI State. A UI state is a way for you to apply a specific configuration to some object on demand.
  • In a Property Mapping. A property mapping is a way for you to instruct the surface to configure displayed edges based upon the values of one or more properties in their backing data.

The structure of an overlay specification can take one of two forms - the simplest is just to specify the overlay type by name:

overlays:[
"Arrow"
]

but there is very little you can do with this, since the overlay will use its default values and be placed at the default location (halfway along the path travelled by the underlying connector). The second way - and the way you'll almost always use - is to specify the overlay by name and to also provide some configuration values:

overlays:[    
{
type:"Arrow",
options:{
width:10,
length:15,
location:1
}
}
]

Here, we've specified an Arrow overlay with a given width and length, and to be located at the end of the path.

All overlays support a few common configuration options:

Interface OverlayOptions

Base options for an overlay.

Members

attributes?: Record
Optional custom attributes to write to the overlay's element.
cssClass?: string
Optional CSS class(es) to add to the overlay's element.
events?: Record
Optional event handlers to attach to the overlay.
id?: string
Optional ID for the overlay. Can be used to retrieve the overlay from a connection.
location?: number
Defaults to 0.5. See docs.

Overlay location

A key concept with Overlays is that of their location.

For an edge, the location of an overlay refers to some point along the path inscribed by the edge. It can be specified in one of three ways:

  • as a decimal in the range [0..1], which indicates some proportional amount of travel along the path inscribed by the edge. The default value of 0.5 is in this form, and it means the default location of an overlay on an edge is a point halfway along the path.
  • as an integer greater than 1, which indicates some absolute number of pixels to travel along the edge from the start point
  • as an integer less than zero, which indicates some absolute number of pixels to travel backwards along the edge from the end point.

Default location

The default location for an overlay is halfway along the path traveled by the connector - location is 0.5. If you specify location:1, then the overlay will be at the end of the path; location:0 puts the overlay at the start.

Overlay types

The Toolkit ships with 4 overlay types, and support for creating custom overlays.

Arrow

Interface ArrowOverlayOptions

Members

attributes?: Record
Optional custom attributes to write to the overlay's element.
cssClass?: string
Optional CSS class(es) to add to the overlay's element.
direction?: number
1 to point forwards (the default), -1 to point backwards.
events?: Record
Optional event handlers to attach to the overlay.
foldback?: number
How far, as a decimal, along the line from head to baseline to fold back into. Defaults to 0.623.
id?: string
Optional ID for the overlay. Can be used to retrieve the overlay from a connection.
length?: number
Length from the head to the baseline. Defaults to 20.
location?: number
Defaults to 0.5. See docs.
paintStyle?: PaintStyle
Optional paint style to use for the arrow.
width?: number
Width of the arrow's baseline. Defaults to 20.

Arrow direction

A point to note is that location:0 for arrow overlays will not reverse the direction in which the arrow is pointing. To have the arrow point backwards along the path you have to provide a value for direction:

overlays:[    
{
type:"Arrow",
options:{
width:10,
length:15,
location:0,
direction:-1
}
}
]

The direction:-1 here instructs the Toolkit to draw the arrow painting backwards. There are only two valid values for direction - 1 and -1. If you provide any other value - or no value - then the Toolkit will use a value of 1, meaning the arrow points forwards.

PlainArrow

This overlay is an extension of Arrow with the foldback parameter's value fixed to 1. This results in an arrow with a flat back.

Diamond

This overlay is an extension of Arrow with the foldback parameter's value fixed to 2. This results in an arrow shaped like a diamond.

Label

Interface LabelOverlayOptions

Members

attributes?: Record
Optional custom attributes to write to the overlay's element.
cssClass?: string
Optional CSS class(es) to add to the overlay's element.
events?: Record
Optional event handlers to attach to the overlay.
id?: string
Optional ID for the overlay. Can be used to retrieve the overlay from a connection.
label:
String, or a function returning a string, for the label.
labelLocationAttribute?: string
Optional name of the attribute that identifies this overlay's location on the path. Defaults to location.
location?: number
Defaults to 0.5. See docs.
useHTMLElement?: boolean
Whether or not to use an HTML element. Defaults to false (uses an SVG element)

The label for a label overlay can be a string or a function, but in practice in the Toolkit edition you'll generally be defining labels as strings, as the values presented to the renderer are extracted from the JSON backing data for each edge

Custom

The custom overlay allows you to create your own overlays, which jsPlumb will position for you. You need to implement one method - create(component) - which is passed the component on which the overlay is located as an argument, and which returns either a DOM element or a valid selector from the underlying library:


overlays:[
{
type:"Custom"
options:{
create:(component) => {
const d = document.createElement("select")
d.innerHTML = "<option value='foo'>foo</option><option value='bar'>bar</option>"
return d
},
location:0.7,
id:"customOverlay"
}
}
]

Here we have created a select box with a couple of values, assigned to it the id of 'customOverlay' and placed it at location 0.7. Note that the 'id' we assigned is distinct from the element's id. You can use the id you provided to later retrieve this overlay using the getOverlay(id) method on a connection.

Custom overlays as endpoints

Since version 6.6.2, for custom overlays at location 0 or 1, ie. the start and end of an edge, the Toolkit writes out a set of data-anchor-** attributes onto the custom overlays' element. In conjunction with a little CSS, this can be used to auto rotate your overlays. It's probably easier to explain with some pictures.

Here is an SVG element that we want to put at either end of our edges:

It'll be a bit smaller than that IRL. So we're going to write a custom overlay which embeds this SVG into it, and we're going to use that custom overlay at locations 0 and 1 on our edges.

Our first pass at a custom overlay definition looked like this:

overlays:[
{
type:"Custom",
options:{
create:function(component) {
const d = document.createElement("div")
d.className="rotating-custom-overlay"
d.style.width = "16px"
d.style.height = "20px"
d.innerHTML = `<svg width="100%" height="100%" viewBox="0 0 16 21">
<rect x="0" y="0" fill="red" width="10" height="21"/>
<rect x="10" y="7" fill="red" width="6" height="7"/>
</svg>`
return d
},
location:1
}
},
...
]

but in fact since we want one of these at either end, we've pulled it into a factory method:

function customOverlayFactory(location) {
return {
type:"Custom",
options:{
create:function(component) {
const d = document.createElement("div")
d.className="rotating-custom-overlay"
d.style.width = "16px"
d.style.height = "20px"
d.innerHTML = `<svg width="100%" height="100%" viewBox="0 0 16 21">
<rect x="0" y="0" fill="red" width="10" height="21"/>
<rect x="10" y="7" fill="red" width="6" height="7"/>
</svg>`
return d
},
location:location
}
}
}

Then we define our overlays as:

overlays:[
customOverlayFactory(0),
customOverlayFactory(1)
]

And this is the result. You can drag the nodes around to see the overlay's orientation switch:

We mentioned above, though, that there's CSS involved. Here's what that looks like:

.rotating-custom-overlay {
transform-origin: center;
}

.rotating-custom-overlay[data-anchor-oy='1'] {
transform: rotate(90deg) translate(-50%,25%) !important;
}

.rotating-custom-overlay[data-anchor-oy='-1'] {
transform: translate(-50%, -75%) rotate(270deg) !important;
}

.rotating-custom-overlay[data-anchor-ox='1'] {
transform: translate(0%, -50%) rotate(0deg) !important;
}

.rotating-custom-overlay[data-anchor-ox='-1'] {
transform: translate(-100%, -50%) rotate(180deg) !important;
}

Here, the data-anchor-** attributes map to the orientation of the anchor at either the source or target of some edge. The orientation of an anchor determines in which direction a connection from that anchor will naturally travel - a discussion of this concept can be found here. You will need to setup similar styles in your app if you want to use this concept.

Thoughts?

We're tempted to put these styles into the default Toolkit stylesheet, although since they would then apply to everyone, perhaps a 'rotatable' flag could be added to custom overlays. We'd be interested to hear your thoughts.