Is there any way of disabling the animation in a D3 force-directed graph?
I am working with this example: https://bl.ocks.org/mbostock/4062045
I want to render the graph without the initial animation, that is, showing all the nodes and links in their final positions.
EDIT
This method simply hides the animation part of the simulation. Please see Gerardo Furtado's answer which performs the simulation without drawing the intermediary results, meaning that the user doesn't have to wait whilst the solution is slowly evolving.
========
The 'animation' is actually the simulation running. It is possible to play with the time that the simulation runs but this might mean that the nodes get stuck at a local minimum - see the documentation here for more details.
You do have the option of adding a listener to the end
event which fires when the simulation has finished. I have created a snippet where the Graph is initially hidden and then appears once it has finished simulating.
An alternative would be to render the chart server-side (if this is an option) and then serve a ready-drawn SVG which could be further manipulated with d3.
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.on('end', function() {
svg.classed('hidden', false)
d3.select('#loading').remove()
});
// I wasn't able to get the snippet to load the original data from https://bl.ocks.org/mbostock/raw/4062045/miserables.json so this is a copy hosted on glitch
d3.json("https://cdn.glitch.com/8e57a936-9a34-4e95-a03d-598e5738f44d%2Fmiserables.json", function(error, graph) {
if (error) {
console.log(error)
};
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) {
return Math.sqrt(d.value);
});
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) {
return color(d.group);
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node.append("title")
.text(function(d) {
return d.id;
});
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
.hidden {
visibility: hidden
}
img {
display: block;
margin-left: auto;
margin-right: auto;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<img id ="loading" src="http://thinkfuture.com/wp-content/uploads/2013/10/loading_spinner.gif" />
<svg width="960" height="600" class="hidden"></svg>