ZoomCharts Documentation

Version: 1.21.1 (2025-02-07)
Switch to Version 2.0 (BETA)

Layout

NetChart has several layout modes available, plus some settings that govern their behavior. The mode is selected by the settings.layout.mode setting and the available modes are:

Static mode

This is the simplest possible mode. NetChart doesn't perform any layout at all, instead all nodes need to be assigned explicit coordinates in the data. Also, pinning (locking) the nodes doesn't do anything in this mode, because nodes don't move by themselves anyway.

Dynamic mode

This is the most advanced (and the default) mode. A physics simulation is used to place the nodes, although the laws of physics in the world of NetChart are slightly different than those in the real world. Nevertheless they are similar enough for the chart to be used intuitively.

In essence, there are 3 forces at play - nodes themselves repulse each other, links act as springs and pull nodes together, and there's a gravity force which attempts to bring everything together. For nodes it is their radius which determines the strength by which they repulse other nodes. This is used even when the nodes are not circular, because the physics simulation treats all nodes as circular. For links there are two settings in the link style - length and strength. Length is the desired length of the link which it will try to contract to, and strength is the "stiffness" of the spring. Larger values mean a stiffer spring.

The simulation is discrete and runs in distinct "steps", and the time between two successive "steps" is always considered to be the same. To adjust for variable framerate, each distinct frame which is actually drawn on the screen can actually contain multiple steps of physics calculations. In addition, there is an "global layout phase" where many steps are calculated at once and the process only stops when either the nodes have stopped moving significantly or a timeout has elapsed. This phase happens when the graph is first shown, and also later if the graph has significant changes, such as new nodes appearing which aren't connected to any existing nodes. When there have been no significant node movements or the user has stopped interacting with the graph, the physics calculations will be suspended and further frames will be drawn without recalculating node positions.

There are also several settings by which the algorithm can be adjusted:

Gravity

Besides the node repulsion and link attraction, the force of gravity is meant for graphs that have several disjoint parts or "clusters". Without gravity these clusters would just fly apart because the nodes in them would repel each other but there would be nothing to pull them together. Again, the gravity force here is unlike the gravity in real world. Rather it's tweaked to bring everything together while having as little impact on performance as possible.

In version 1.17.0 the gravity force was reworked and multiple settings were added to allow for tweaking of different scenarios.

In general, the gravity force can affect either individual nodes, or whole clusters. If it is set to affect individual nodes, then the gravity force is calculated separately for each node, independent of other nodes. If it is set to affect whole clusters, then the gravity force is calculated for the cluster as a whole, and then applied equally to all nodes in that cluster.

Gravity force pulls the object (node or cluster) towards some sort of center. This can be the center of the cluster, the center of the graph, or the nearest locked node (see below). Unlike real world, this force is linearly proportional to the distance to this center - the further the object is from the center, the stronger the force.

The center itself can also be calculated in two different ways - weighted and geometric. A "weighted" calculation means that the average x/y coordinate is calculated amongst all the nodes, and the radius of each node is used as a "weight". Basically it's the mass center. If all the nodes have the same radius, then the x/y of the center will be the arithmetic average of all nodes. If there are two nodes and one node has a radius which is twice as big than that of the other node, then the x/y of the center will be closer to the larger node (the distance to the smaller node will be twice as big as the distance to the larger node). Etc.

A "geometric" calculation on the other hand approximates a circle around all the nodes and uses the center of that circle. Each node is approximated as a circle and that is further approximated as 8 equally spaced points on it. The smallest possible circle is then circumscribed around all these points and the center of that circle then becomes the gravity center.

Note: when talking about "locked" nodes, it means the nodes which are "pinned". Nodes also become "temporarily locked" while the user hovers over them with the mouse, but for the purpose of gravity calculations those are still considered to be "free". Using only locked nodes to determine the gravity center(s) allows an easier exploration of the graph (it can be "pulled apart" by the user) as well as a way of programmatically overriding the gravity centers. If the default settings do not produce a pleasing layout it is possible to assign specific positions to a few key nodes and ensure a better result.

The settings that can be tweaked, starting with 1.17.0, are:

Radial mode

The radial mode arranges the nodes in a circle, starting with one central node and radiating outwards. If there are multiple disconnected clusters of nodes, each cluster will be laid out in a circular fashion and all the circles will be placed next to each other.

This mode works best if the graph doesn't have any cycles in it. If there are cycles, some links will be ignored for the layout. You can determine which links were ignored by checking the .background property on the links. It will be true for the ignored links, and false for the links that were used in determining the layout. The direction of the links is ignored.

The central node for the first cluster is determined in the following fashion:

  1. Check which node was focused most recently. If there is one, use that.
  2. If no nodes are focused, check the navigation.initialNodes. If any of those nodes are availabe, use that.
  3. Finally, if there is nothing else, just pick any node that is visible.

For the remaining clusters one node will be picked on random to be in the center.

This mode works well together with the Focusnodes navigation. As the user navigates through the graph by focusing different nodes, the latest node will become the central one, its immediate neighbors will be in the first surrounding circle, etc.

The settings that affect this mode are:

Hierarchy mode

This mode produces a top-down "tree", like an organization chart. In this mode the direction of the links determines which nodes are above and which links are below - links always flow "away" from the root node. That however means that it's not possible to directly specify the "root" node since it follows naturally from the direction of the links. If a node has more than one parent or there are loops in the graph, some links will be ignored to produce a true tree structure. Again, it's possible to check the .background property to see which links are ignored and which are used.

In case of multiple disconnected clusters, each cluster will be layed out separately and then they will be placed next to each other. The distance between two trees is always twice that of groupSpacing.

The settings that affect this mode are:

X