Skip to main content

Anchor position finders (Toolkit edition)

· 5 min read
Simon Porritt

Version 5.4.0 of the Community edition has support for a new concept - the ability to specify at drag start/stop what the location of an anchor should be, discussed in this post. This functionality is exposed to users of the Toolkit edition by supporting anchorPositionFinder values in the view.


This demonstration exhibits the same behaviour shown in the Community edition demonstration linked above: when you drop a connection on the right hand side of an element, its anchor is on the right face; when you drop on the left hand side, the anchor is on the left face.

Anchor position finders

These are the render params used to create this:

{  layout:{    type:"Absolute"  },  defaults:{    anchor:"Continuous",    endpoint:"Dot"  },  zoomToFit:true,  templates:{        "jtk-template-default":'<div data-jtk-source="true" data-jtk-target="true" data-jtk-target-port-type="twosides"></div>'  },  view:{    ports:{        twosides:{            anchorPositionFinder:function(el, elxy, vertex) {                                var x = elxy.x < 0.5 ? 0 : 1,                    ox = x === 0 ? -1 : 1;                                                    return [x, 0.5, ox, 0]            }           }    }      }

Aside from the anchorPositionFinder function itself, the key piece to grok in this setup is the way the node template is hooked up to the view. This is the html for each node:

<div data-jtk-source="true"         data-jtk-target="true"         data-jtk-target-port-type="twosides">        </div>

So we've got three attributes declared here:

  • data-jtk-source="true" Indicates the node is a connection drag source
  • data-jtk-target="true" Indicates the node is a connection drag target
  • data-jtk-target-port-type="twosides" Tells the Toolkit that this target should use the port definition called twosides, which is where our anchorPositionFinder is declared. Note that in the Toolkit you can make use of logical port mappings like this without actually declaring that the target is a port on the node. In this case, the node itself is still the target, but we're using the twosides port definition to define some behaviour.

In this demonstration we don't declare a node type; instead we use jtk-template-default as the ID of the template we provide. In the absence of any other information about how to render a node, the Toolkit will look for a template with that ID.

Another Example#

To illustrate the flexibility of this arrangement, let's create something more complex. We'll have three node types - red, blue and green.

  • red nodes will just use the default anchors (Continuous)
  • green nodes will use the anchor strategy from the first example
  • blue nodes will place an anchor exactly where the connection was dropped.
Anchor position finders - complex example

The render params for this example are as follows:

{  layout:{    type:"Absolute"  },  defaults:{    anchor:"Continuous",    endpoint:"Dot"  },  zoomToFit:true,  view:{    nodes:{        red:{            template:'<div data-jtk-source="true" data-jtk-target="true" style="background-color:red"></div>'        },        green:{          template:'<div data-jtk-source="true" data-jtk-target="true" style="background-color:mediumseagreen"></div>',          anchorPositionFinder:function(el, elxy, vertex) {                              var x = elxy.x < 0.5 ? 0 : 1,                  ox = x === 0 ? -1 : 1;                                                return [x, 0.5, ox, 0]          }        },        blue:{            template:'<div data-jtk-source="true" data-jtk-target="true" style="background-color:cadetblue"></div>',            anchorPositionFinder:function(el, elxy, vertex) {                                return [elxy.x, elxy.y, 0, 0]            }        }        }      }}

Here, we map a template for each node type, and then for blue and green types, we provide an anchorPositionFinder. The logic in the finder for green is as shown in the example above. For the blue node type, recall that elxy is the proportional location of the drop event on the drop element. This coordinate system is the same that Anchors use, so we can just return the values from elxy directly.

Note also that in this example we have declared anchorPositionFinder on node definitions, whereas in the previous example we declared the position finder on a port definition. You can define them on any vertex definition - node, port or group.


If you're new to the Toolkit and you'd like to know more about views, you can read about them in the documentation