Skip to main content

Anchors

Anchors#

An anchor models the notion of where on an element a connector should connect - it defines the location of an endpoint. It is key UI concept.

There are four main types of Anchors:

  • static - these are fixed to some point on an element and do not move. They can be specified using a string to identify one of the defaults that the Toolkit ships with, or an array describing the location (see below)

  • dynamic - these are lists of static anchors from which the Toolkit picks the most appropriate one each time a connection is painted. The algorithm used to determine the most appropriate anchor picks the one that is closest to the center of the other element in the connection. A future version of jsPlumb might support a pluggable algorithm to make this decision.

  • perimeter anchors - these are anchors that follow the perimeter of some given shape. They are, in essence, dynamic anchors whose locations are chosen from the perimeter of the underlying shape.

  • continuous anchors - These anchors are not fixed to any specific location; they are assigned to one of the four faces of an element depending on that element's orientation to the other element in the associated connection. Continuous anchors are slightly more computationally intensive than static or dynamic anchors because jsPlumb is required to calculate the position of every connection during a paint cycle, rather than just connections belonging to the element in motion.


Static Anchors#

jsPlumb has nine default anchor locations you can use to specify where the connectors connect to elements: these are the four corners of an element, the center of the element, and the midpoint of each edge of the element:

  • Top
  • TopRight
  • Right
  • BottomRight
  • Bottom
  • BottomLeft
  • Left
  • TopLeft
  • Center

The AnchorLocations enumeration contains these values.

Each of these string representations is just a wrapper around the underlying array-based syntax [x, y, dx, dy], where x and y are coordinates in the interval [0,1] specifying the position of the anchor, and dx and dy,which specify the orientation of the curve incident to the anchor, can have a value of 0, 1 or -1. For example, [0, 0.5, -1, 0] defines a Left anchor with a connector curve that emanates leftward from the anchor. Similarly, [0.5, 0, 0, -1] defines a Top anchor with a connector curve emanating upwards.

anchor:"Bottom"

or

anchor: AnchorLocations.Bottom

is identical to:

anchor:[ 0.5, 1, 0, 1 ]
Default Anchor Positions

Anchor Offsets#

In addition to supplying the location and orientation of an anchor, you can optionally supply two more parameters that define an offset in pixels from the given location. Here's the anchor specified above, but with a 50 pixel offset below the element in the y axis:

anchor:[ 0.5, 1, 0, 1, 0, 50 ] 

Dynamic Anchors#

These are Anchors that can be positioned in one of a number of locations, choosing the one that is most appropriate each time something moves or is painted in the UI.

There is no special syntax for creating a Dynamic Anchor; you just provide an array of individual static anchor specifications, eg:


anchor:[ [ 0.2, 0, 0, -1 ],  [ 1, 0.2, 1, 0 ], [ 0.8, 1, 0, 1 ], [ 0, 0.8, -1, 0 ] ]

Note that you can mix the types of these individual static anchor specifications:

anchor: [ [ 0.2, 0, 0, -1 ],  [ 1, 0.2, 1, 0 ], "Top", "Bottom" ];

Default Dynamic Anchor#

jsPlumb provides a dynamic anchor called AutoDefault that chooses from Top, Right, Bottom and Left:

anchor:"AutoDefault"

or with ES6/Typescript:

anchor: AnchorLocations.AutoDefault

These two nodes have an endpoint with an AutoDefault anchor - drag them around and see how they choose from Top, Left, Bottom and Right depending on their orientation.

Dynamic anchors

Location Selection#

The algorithm that decides which location to choose just calculates which location is closest to the center of the other element in the Connection. It is possible that future versions of jsPlumb could support more sophisticated choice algorithms, if the need arose.

Draggable Connections#

jsPlumb locks the position of a dynamic anchor when you start to drag a connection from it, and unlocks it once the connection is either established or abandoned. At that point you may see the position of the dynamic anchor change, as jsPlumb optimises the connection.


Perimeter Anchors#

These are a form of dynamic anchor in which the anchor locations are chosen from the perimeter of some given shape. jsPlumb supports six shapes:

  • Circle
  • Ellipse
  • Triangle
  • Diamond
  • Rectangle
  • Square

Rectangle and Square are not, strictly speaking, necessary, since rectangular shapes are the norm in a web page. But they are included for completeness.

anchor:{ type:"Perimeter", options:{ shape:"Circle" } }

In this example our anchor will travel around the path inscribed by a circle whose diameter is the width and height of the underlying element.

Circle perimeter anchor

Note that the Circle shape is therefore identical to Ellipse, since it is assumed the underlying element will have equal width and height, and if it does not, you will get an ellipse. Rectangle and Square have the same relationship.

By default, jsPlumb approximates the perimeter with 60 anchor locations. You can change this, though:

anchor:{ type:"Perimeter", options:{ shape:"Circle", anchorCount:150 } }

Obviously, the more points the smoother the operation. But also the more work your browser has to do.

Rotating a Perimeter Anchor#

You can supply a rotation value to a Perimeter anchor. Here's how you would use it in the Community edition:

anchors:[    { type:"Perimeter", options:{ shape:"Triangle", rotation:25 } },    { type:"Perimeter", options:{ shape:"Triangle", rotation:-335 } }] 

Note that the value must be supplied in degrees, not radians, and the number may be either positive or negative. In the example above, both triangles are of course rotated by the same amount.


Continuous Anchors#

As discussed above, these are anchors whose positions are calculated by jsPlumb according to the orientation between elements in a connection, and also how many other Continuous anchors happen to be sharing the element. You specify that you want to use Continuous anchors using the string syntax you would use to specify one of the default static anchors, for example:

anchor:"Continuous"

Note in this example we specified only "anchor", rather than "anchors" - jsPlumb will use the same spec for both anchors. But we could have said this:

anchors:["Bottom", "Continuous"]

...which would have resulted in the source element having a static anchor at BottomCenter. In practise, though, it seems the continuous anchors work best if both elements in a connection are using them.

Try dragging these nodes around and see how the anchors adapt their positions:

Continuous anchors

Choosing faces for a Continuous anchor#

By default, a Continuous anchor will choose points from all four faces of the element on which it resides. You can control this behaviour, though, with the faces parameter on the anchor spec:

anchor:{ type:"Continuous", options:{ faces:[ "top", "left" ] } }

Allowed values are:

  • top
  • left
  • right
  • bottom

If you provide an empty array for the faces parameter, jsPlumb will default to using all four faces.


Associating CSS classes with Anchors#

The array syntax discussed above supports an optional 7th value, which is a string that represents a CSS class. This CSS class is then associated with the anchor, and applied to the anchor's endpoint and element whenever the anchor is selected.

A static Anchor is of course always "selected", but a dynamic anchor cycles through a number of different locations, and each of these may have a different CSS class associated with it.

The CSS class that gets written to the endpoint and element is prefixed with the associated jsPlumb instance's endpointAnchorClass prefix, which defaults to:

jtk-endpoint-anchor-

So if you had the following, for example:

anchor:[0.5, 0, 0, -1, 0, 0, "top" ]

Then the endpoint created by jsPlumb and also the element someDiv would have this class assigned to them:

jtk-endpoint-anchor-top

An example using dynamic anchors:

anchor:[    [ 0.5, 0, 0, -1, 0, 0, "top" ],    [ 1, 0.5, 1, 0, 0, 0, "right" ]    [ 0.5, 1, 0, 1, 0, 0, "bottom" ]    [ 0, 0.5, -1, 0, 0, 0, "left" ]  ]

Here, the class assigned to the endpoint and element would cycle through these values as the anchor location changes:

jtk-endpoint-anchor-topjtk-endpoint-anchor-rightjtk-endpoint-anchor-leftjtk-endpoint-anchor-bottom

Note that if you supply a class name that consists of more than one term, jsPlumb will not prepend the prefix to each term in the class:

anchor:[ 0.5, 0, 0, -1, 0, 0, "foo bar" ]

would result in 2 classes being added to the endpoint and element:

jtk-endpoint-anchor-foo

and

bar