ZoomCharts Documentation
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"
- no automatic layout is used. Node positions must be passed in the data."dynamic"
- force-directed layout algorithm. Nodes repulse each other and links act as "springs" which pull them together. This is the default."radial"
- nodes are placed in a circle, starting from a center node and moving outwards."hierarchy"
- nodes are places in a top-down tree-like structure which can also be rotated.
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:
globalLayoutOnChanges
- Whether to perform the global layout phase on all changes of the graph (true
), or only on significant changes (false
). Performing more often will give a nicer layout, but at the cost of performance.initialLayoutMaxTime
- Timeout in milliseconds. Timeout for the global layout phase if it was triggered as a result of significant changes.incrementalLayoutMaxTime
- Timeout in milliseconds. Timeout for the global layout phase if it was triggered as a result of insignificant changes (only withglobalLayoutOnChanges=true
).layoutFreezeMinTimeout
- Timeout in milliseconds. If there has been no significant node movement for this long, the layout is suspended entirely and no more physics calculations are done.layoutFreezeTimeout
- Timeout in milliseconds. If there has been no user interaction for this long, the layout is suspended entirely and no more physics calculations are done, even if there are still nodes with significant movement.advanced.adaptiveFreezeTreshold
- The threshold which determines if node movement is still "significant". This is a unitless coefficient and if you want to change it, you'll need to find a good value experimentally.nodeSpacing
- The desired minimum distance between nodes. Note that in extremely crowded graphs this might get violated anyways - the physics simulation doesn't give any guarantees about anything.aspectRatio
- Whether to compensate for a non-square chart area. If set totrue
the resulting node placement will be "stretched" to better fill the available space.
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:
strength
- A coefficient for calculting the magnitude of the gravity force. A larger coefficient will give a stronger gravity. Specifiying0
will disable the gravity entirely. Negative values are allowed, but will probably be useless. They will produce anti-gravity which will only get stronger as the objects get further from the center.from
- what the object is that the gravity affects. Can be either"node"
,"cluster"
or"auto"
. In case of"auto"
it will use"node"
in most cases, except when there is just one cluster with less than 100 nodes. In that case"cluster"
will be used.fromCenter
- iffrom="cluster"
, then this specifies how (weighted or geometric) the center of the cluster is calculated which the gravity will then attract. Note that only unlocked nodes are used for calculating this center.to
- The center to which the gravity will attract objects. This has several possible values:"nearestLockedNode"
- this works only iffrom="node"
. For each node the nearest locked node will be found and the gravity will pull towards that. "Nearest" in this case means with least links between them, not geometrically nearest."cluster"
- For each cluster a separate center is calculated and the gravity pulls all nodes in that cluster to the center of that cluster. All nodes in the cluster are used for calculating the center."clusterLockedNodes"
- The same as"cluster"
, but only locked nodes are used for calculating the center."graph"
- A single center from all the nodes in the graph is calculated and gravity pulls only towards that."graphLockedNodes"
- The same as"graph"
, but only locked nodes are used for calculating the center.
toCenter
- this is ignored forto="nearestLockNode"
, but for all other settings it specifies how (weighted or geometric) the center is calculated towards which the gravity will pull.
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:
- Check which node was focused most recently. If there is one, use that.
- If no nodes are focused, check the
navigation.initialNodes
. If any of those nodes are availabe, use that. - 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:
nodeSpacing
- The desired minimum distance between nodes. The distance between the circles will be at least this large, however the distance between neighboring nodes may be smaller in some cases.twoRingRadialLayout
- If set totrue
and the first ring around the center node has enough nodes, they will be positioned in a "zig-zag" pattern in two rings instead. This produces a more compact layout for this level.
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:
nodeSpacing
- The minimum horizontal distance between nodes. This will always be honored.rowSpacing
- The minimum vertical distance between nodes. If not specified, assumed to be the same asnodeSpacing
. This will always be honored.groupSpacing
- If two nodes in the same level (horizontal neighbors) have different parents they will usegroupSpacing
as their horizontal distance, instead ofnodeSpacing
. This makes it easier to distinguish between "groups" of nodes. If not specified,groupSpacing
is assumed to be twice the length ofnodeSpacing
.rotation
- It's possible to rotate this layout and thus instead of a top-down tree to produce a bottom-up tree or a left-right tree or anything else. This parameter is the rotation angle, in degrees clockwise.0
means a top-down tree,180
is a bottom-up tree,90
is a right-left tree, etc. In the case of multiple disconnected clusters, the whole row is rotated. So, if for0
all the trees are horizontally next to each other, then for90
they will be vertically above each other, etc.