Skip to main content

Paths

A Path represents the path from one vertex (a node/port/group) through a series of edges and intermediate vertices to another vertex. The jsPlumb Toolkit provides several methods for the creation and manipulation of paths, as well as animating overlays along a path.

You can work with paths through both an instance of the jsPlumb Toolkit and any Surfaces. The object representing a path differs slightly between the two, in that paths created from a Surface support a few extra (UI-related) methods, such as setVisible.

Getting a Path

To get a Path, you call getPath on either a Toolkit instance or a Surface, with a valid path spec. A quick example to kick off:

toolkit.getPath({
source:someNode,
target:someOtherNode
});

This will return you the shortest path from someNode to someOtherNode, where the Path length is related to its cost.

Paths including ports

By default, the Toolkit will search for paths in "strict" mode, meaning if you supply a Node/Group as source/target, then only Edges directly connected to that Node/Group will be traversed in the search for a Path. Switching off "strict" more relaxes this restriction, and also includes Edges connected to any Ports on the given Node/Group. See below.

Path specs

This is the full list of supported parameters to the getPath method.

Interface PathOptions

Path specification.

Members

edgeFilter?:
This function is given each Edge's backing data and asked to return true or false - true means include the Edge, false means exclude it.
nodeFilter?:
This function is given each Node/Group's backing data and asked to return true or false - true means include the Node/Group, false means exclude it.
source:
Path source. Either a vertex (node/group/port) or a vertex id.
strict?: boolean
Sets whether or not paths are searched strictly by the given source/target. If you supply a node as the source, but there are only edges connected to ports on that node, by default these edges will be ignored. Switching strict to false will mean these edges are considered.
target:
Path target. Either a vertex (node/group/port) or a vertex id.

Filtering nodes

toolkit.getPath({
source:someNode,
target:someOtherNode,
nodeFilter:function(n) {
return n.data.type != "aTypeIWantToIgnore";
}
});

Here we pass in a function that will be called for every prospective Node in the Path. If it returns false then the Graph treats the Node as if it were at a distance of Infinity - not reachable.

Filtering edges

You can also provide an edgeFilter to control which Edges your Path will traverse:

toolkit.getPath({
source:someNode,
target:someOtherNode,
edgeFilter:function(e) {
return e.data.type != "aTypeIWantToIgnore";
}
});
tip

The arguments to these functions are Node or Edge objects from the Toolkit. You may wish to use information contained in those classes to make your decisions, but if you just want to access the original data, you use the data member as shown above.

Paths in the UI

Calling getPath(...) on a Surface returns you a UIPath object, which contains a Path and offers a few extra methods for manipulating the appearance of the components of the path. All of the class manipulation methods take a space-delimited string as argument. See below for a detailed list of the available methods on a UIPath.

note

Calling any of the methods from the basic Path object on the result of a getPath call to a Surface that result in a change to the data model will cause those data model changes to be communicated automatically to any other Surface registered on the given Toolkit instance.

Animating paths

The surface component supports tracing a path between a given source and target node using an overlay.


import { newInstance } from "@jsplumbtoolkit/browser-ui"

// setup two nodes and connect

let toolkit = newInstance()
let renderer = toolkit.render(someElement)
toolkit.load({
data:{
nodes: [ a bunch of nodes. let's pretend they have IDs from 1 - 34 ],
edges:[ a bunch of edges ]
}
});

let transport = renderer.tracePath({
source:1,
target:23,
overlay:"Arrow"
});

if (!transport.pathExists) {
alert("There was no such path");
}

In this example we've attempted to trace an arrow overlay along the shortest path from node 1 to node 23, using the default animation options, which are:

  • travel at 100 pixels per second
  • use a frame rate of 30 frames per second
  • dwell on each intermediate element for 250 milliseconds

The return values from the tracePath method is a PathTransport object, which offers the following methods:

  • play() Starts the animation
  • pause() Pauses the animation
  • cancel() Cancels the animation
  • bind(event:string, handler:Function) Binds an event handler. Only one event - "state" - is fired, in fact, and it's generally better practise to supply a listener to the tracePath method call instead, because binding to the transport after it has been created means you will miss the initial start state event change.

We can enhance the previous call, then, with an event listener like this:


import { newInstance } from "@jsplumbtoolkit/browser-ui"

function stateChange(newState) {
console.log("The new state is " + newState);
}

// setup two nodes and connect
let toolkit = newInstance()
let renderer = toolkit.render(someElement)
toolkit.load({
data:{
nodes: [ a bunch of nodes. let's pretend they have IDs from 1 - 34 ],
edges:[ a bunch of edges ]
}
});

let transport = renderer.tracePath({
source:1,
target:23,
overlay:"Arrow",
listener: stateChange
});

if (!transport.pathExists) {
alert("There was no such path");
}

The Path Tracing demonstration has an example of a full setup with an event listener and play/pause/cancel controls.

Animation Options

You can change the default animation options if you need to:

const transport = renderer.tracePath({
source:1,
target:23,
overlay:"Arrow",
options:{
speed: 25, // pixels per second
rate: 60 // frames per second
dwell: 50 // dwell on intermediate elements for 50 milliseconds
}
});

Tracing a specific Path

The two examples given so far do not mandate any specific path to travel from the source to the target, so the Toolkit will pick the shortest path (which is controlled by both number of hops and edge cost if you have provided that for any of your edges). However, you can supply any path to this method, should you want to.

To get a path that is not the shortest path you will need to make use of a nodeFilter and/or edgeFilter when you call getPath on some Toolkit instance, as discussed above. An example:

let path = toolkit.getPath({
source:1,
target:23,
edgeFilter:(edge) => {
return !edge.data.type === "aTypeIWouldIgnore"
}
});

This path can then be passed to tracePath instead of providing a source and target:

renderer.tracePath({
path:path,
overlay:"Arrow",
options:{
speed: 25, // pixels per second
rate: 60, // frames per second
dwell: 50 // dwell on intermediate elements for 50 milliseconds
}
});

CSS Classes

During the lifetime of a path traversal, the following classes are used:

ClassAssigned ToPurpose
jtk-animate-node-traversingNodesIndicates the path is currently dwelling on the given node/group
jtk-animate-edge-traversableEdgesAssigned to all edges that will be traversed at some point during the path traversal
jtk-animate-edge-traversingEdgesAssigned to an edge is currently being traversed
jtk-animate-edge-traversedEdgesAssigned to an edge that has already been traversed during the path traversal

Events

These events will be fired by the renderer during a path traversal:

EventDescriptionParameters
startOverlayAnimationFired at the beginning of the traversal.connection:Connection
endOverlayAnimationFired at the very end of the traversal.connection:Connection
startNodeTraversalFired when a node has been reached and is being traversed.
endNodeTraversalFired at the end of traversing a Node.

API details

The Path object

API docs for the basic Path object, as used by an instance of the Toolkit, can be found here

caution

Once you have executed one of the delete*** methods on a path, your path may contain references to objects that no longer exist in the Toolkit.

The UIPath object

API docs for the UIPath object, returned from a getPath call on a Surface, can be found here