Search code examples
javascriptd3.jscenteringforce-layout

interpreting the d3 centering force


D3's force simulation centering force uses the following code where:

  • n equals the number of nodes,
  • x equals the centering x value
  • y equals the centering y value
  • sx and sy being as 0.

source code

First the force does this:

for (i = 0; i < n; ++i) {
  node = nodes[i], sx += node.x, sy += node.y;
}

And then:

for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, i = 0; i < n; ++i) {
  node = nodes[i], node.x -= sx, node.y -= sy;
}

How is this a centering force?

What does the first part and second part do respectively?


Solution

  • D3's centering force doesn't push nodes to the center, it moves nodes so that their center of gravity is (closer to) the specified location (with all nodes having equal mass). In other words it does not exert a gravitational pull on any individual node. Instead, if collectively the nodes are all located to the right of the specified center, they are all equally translated so that the actual center of gravity approaches the specified center of gravity. In this way it does not pull any individual node towards the center, it pulls all nodes equally towards the specified center (ie it pulls the graphs as a single entity towards the center).

    The first part sums up the positioning of the nodes' x and y values as sx and sy (my guess is the s stands for sum). The second part finds the average position using these totals (sx/n - x where n equals number of nodes and x the center x value) and applies the same correction to each node based on the strength of the effect.

    If you are looking to pull nodes closer to a centering point, this force will not help. Instead you can use d3.forceX and d3.forceY which will:

    The x- and y-positioning forces push nodes towards a desired position along the given dimension with a configurable strength. (docs)

    Here the x and y values will attract nodes, individually, to a specified x value, y value, or coordinate depending on if you use one or both of d3.forceX and d3.forceY.