Despite this question already having an accepted answer, the proposed solution is not the correct way to disable the animation in a D3 force chart. The browser is still moving the nodes and links at every tick! You just don't see them moving, but the browser is moving them, doing a lot of computation and wasting a lot of time/resources. Also, you don't need server side for this.
My answer proposes a different solution, which actually don't draw the animation. You can see it in this code by Mike Bostock (D3 creator), for instance.
This solution is easy to follow when you understand what is the tick
function: it's just a function that computes all the positions in the simulation and advances one step. Despite the vast majority of D3 force-directed graphs drawing the nodes and the links at every tick, you don't need to do that.
Here is what you can do:
Stop the simulation using stop()
, immediately after defining it:
var simulation = d3.forceSimulation(graph.nodes)
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.stop();//stop the simulation here
Make the simulation run without drawing anything. That's the most important step: you don't have to move the elements at each tick. Here, I'm running 300 ticks, which is approximately the default number:
for (var i = 0; i < 300; ++i) simulation.tick();
Then, simply use the properties created by the simulation (x
, y
, source
, target
) to draw the circles and the lines, just once:
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
Here is the linked blocks with those changes only: http://bl.ocks.org/anonymous/8a4e4e2fed281ea5e2a5c804a9a03783/85ced3ea82a4bed20a2010530562b655d8f6e464
Compare the time of this solution versus the time of the "hiding-the-nodes" solution (the accepted answer). This one here is way faster. In my tests, I got this results:
- "hiding-the-nodes" solution: around 5000ms
- This solution: around 200ms
That is, 25 times faster.
PS: for simplicity, I removed the ticked
function in the forked blocks. If you want to drag the nodes, just add it back.
EDIT for D3 v5.8
Now that D3 v5.8 allows passing the number of interactions to simulation.tick()
you don't even need the for
loop anymore. So, instead of:
for (var i = 0; i < 300; ++i) simulation.tick();
You can just do:
simulation.tick(300);