Skip to main content

Force directed layout

ForceDirected class in the layout namespace implements automatic layouts for graphs using a force-directed approach. This is useful for, usually larger, undirected graphs.

Usage

Force directed layout auto-layouts graphs based on three forces: repulsive force (forces nodes to move out of each other), attractive force (tries to get nodes together like a spring) and a gravity force (tendency of the nodes to move to a certain point).

The ForceDirected constructor accepts a couple of parameters for configuring the layout. The gravityCenter parameter is the point the nodes tend to move to. This is usually set to the center of the area where the nodes are to be laid out. charge parameter affects the repulsive force. Bigger the parameter is, bigger the repulsive force. linkDistance and linkStrength both affect the attractive force (you can think of it as parameters of a spring that tights together two nodes). Bigger the linkStrength, bigger the attractive force between two connected nodes. On the other hand, smaller the linkDistance, shorter links you allow and so the attractive force is bigger between two connected nodes.

There is no one-fits-all set of parameters that would give great result for all possible graphs. Therefore, it is suggested that you to play with the parameters, try to set different values so that it gives a good result for your use case.

You can control the layout process using start() and step() methods. start() method initiates the layout process, while step() method applies forces to the graph and updates the position of shapes.

import { layout } from '@joint/plus';

const graphLayout = new layout.ForceDirected({
graph: graph // or array of selected cells
x: 0,
y: 0,
width: 600,
height: 400,
gravityCenter: { x: 300, y: 200 },
charge: 180,
linkDistance: 30
});

graphLayout.start();

Array.from({ length: 100 }).forEach(() => { graphLayout.step(); });
note

It is recommended to use the requestAnimationFrame for stepping the layout. JointJS provides helper function util.nextFrame() for working with animation.

Here is the example of force directed layout in action:

Stay in the know

Be where thousands of diagramming enthusiasts meet

Star us on GitHub