Automatic layout of directed graphs. This plugin uses the open-source (MIT license) Dagre library internally. It provides a wrapper so that you can call the layout directly on JointJS graphs.

Note that you must include both the Dagre and Graphlib libraries as dependencies if you wish to use the layout.DirectedGraph plugin.

Usage

joint.layout.DirectedGraph plugin exposes the joint.layout.DirectedGraph.layout(graphOrElements, opt) function. The first parameter graphOrElements is the joint.dia.Graph or an array of joint.dia.Elements we want to layout. The second parameter options is an object that contains various options for configuring the layout.

var graphBBox = joint.layout.DirectedGraph.layout(graph, {
    nodeSep: 50,
    edgeSep: 80,
    rankDir: "TB"
});
console.log('x:', graphBBox.x, 'y:', graphBBox.y)
console.log('width:', graphBBox.width, 'height:', graphBBox.height);

A full blog post explaining this example in more detail can be found here.

Example with clusters

Configuration

The following table lists options that you can pass to the joint.layout.DirectedGraph.layout(graph, opt) function:

nodeSepa number of pixels representing the separation between adjacent nodes in the same rank
edgeSepa number of pixels representing the separation between adjacent edges in the same rank
rankSepa number of pixels representing the separation between ranks
rankDirdirection of the layout (one of "TB" (top-to-bottom) / "BT" (bottom-to-top) / "LR" (left-to-right) / "RL" (right-to-left))
marginXnumber of pixels to use as a margin around the left and right of the graph.
marginYnumber of pixels to use as a margin around the top and bottom of the graph.
resizeClustersset to false if you don't want parent elements to stretch in order to fit all their embedded children. Default is true.
clusterPaddingA gap between the parent element and the boundary of its embedded children. It could be a number or an object e.g. { left: 10, right: 10, top: 30, bottom: 10 }. It defaults to 10.
setPosition(element, position)a function that will be used to set the position of elements at the end of the layout. This is useful if you don't want to use the default element.set('position', position) but want to set the position in an animated fashion via transitions.
setLinkVertices(link, vertices)a function that will be used to set the vertices of links at the end of the layout. This is useful if you don't want to use the default link.set('vertices', vertices) but want to set the vertices in an animated fashion via transitions.

Additionally, the layout engine takes into account some properties on elements/links to fine tune the layout further. These are:

minLen Link specific The number of ranks to keep between the source and target of the link.

The layout() function returns an object that contains width and height of the resulting graph.

API

The layout.DirectedGraph plugins extends the joint.dia.Graph type with functions that make it easy to convert graphs to and from the Graphlib graph format. This allows you to easily use many of the graph algorithms provided by this library.

toGraphLib()

Convert the JointJS joint.dia.Graph object to the Graphlib graph object.

var graph = new joint.dia.Graph;
// ... populated the graph with elements connected with links
graphlib.alg.isAcyclic(graph.toGraphLib())      // true if the graph is acyclic

fromGraphLib(glGraph, opt)

Convert the Graphlib graph representation to JointJS joint.dia.Graph object. opt.importNode and opt.importEdge are functions that accept a Graphlib node and edge objects and should return JointJS element/link.

var g = new graphlib.Graph();
g.setNode(1);
g.setNode(2);
g.setNode(3);
g.setEdge(1, 2);
g.setEdge(2, 3);

var graph = new joint.dia.Graph;
graph.fromGraphLib(g, {
    importNode: function(node) {
        return new joint.shapes.basic.Rect({
            position: { x: node.x, y: node.y },
            size: { width: node.width, height: node.height }
        });
    },
    importEdge: function(edge) {
        return new joint.dia.Link({
            source: { id: edge.v },
            target: { id: edge.w }
        });
    }
});