This is prelude to constructing tree-like graphs using the force layout.
when coding constraints which are really strict, e.g. binding a certain node or set of nodes
to a specific y coordinate (node.depth ~ y position in a vertical tree), it is opportune
to ‘insinuate’ the constraint rather than enforce it, i.e. you should apply the constraint
as if it was a force, i.e. verlet-integrate the delta, using the tick.alpha strength.
Of course nothing stops you from strengthening the applicatiuon of the constraint
when the alpha
value is near zero (i.e. we’re almost stable/at the end of the force iteration).
you can edit both .x/.y and .px/.py in the tick
handler, but any ‘force-like’ constraints
should best be applied to the .px/.py components as then they will mix with the repulse and
verlet integration logic in the next round.
given the two items above, it is opportune to code a constraint like ‘stay within visible area’ as a dual constraint: one which clips the x/y node coordinates to ensure they stick within the visible area, and a second part which is a ‘force’ applied to repulse any nodes close to the edge(s): if you don’t do the latter, you’ll get graph views where a lot of nodes hug the edge(s) and don’t resolve themselves to move back into the visible area proper. (Drag any graph to the edge with such a constraint and you’re getting a very jittery graph where a lot of the nodes bounce against the edges but don’t ‘move away’. That’s why you need such a second ‘repulse force’ to make this happen and make the graph look good, even when dragged near the edge.
All constraints are applied in the force.on(“tick”) event handler.
We also implement drag behaviour, which, like any other use of node.fixed
, will add a .px/.py coordinate
pair for each node under the hood. To prevent any ‘Crazy Ivan jumping’ of nodes and other unexpected behaviour, we must ensure that
.x/.y and .px/.py match once we are done in the force.tick handler, otherwise the
next mouseenter/drag will behave very oddly.
It is always a good rule to set both .px/.py and .x/.y when you update force nodes’ x/y coordinates.
This example is derived off the D3 example examples/force/force-collapsible.html
.
The code requires a D3 version which includes (pull request #803](https://github.com/mbostock/d3/pull/803).