Reputation: 41
I would like to delay the start of a force simulation by about 2 seconds. How do I do this? I feel like you should be able to say "if tick < n, don't start" or something like that... but I do not understand how or even if this is possible. I have reviewed the documentation but don't know.
Here is the code I am working with if that matters.
var simulation = d3.forceSimulation(data)
.force('charge', d3.forceManyBody().strength(33))
.force('x', d3.forceX().x(function(d) {
return d.xx;
}))
.force('y', d3.forceY().y(function(d) {
return d.yy;
}))
.force('collision', d3.forceCollide().radius(function(d) {
return d.radius;
}))
.on('tick', ticked);
function ticked() {
var u = d3.select('svg')
.selectAll('text')
.filter(function(d, i) { return i != 0; })
.data(data);
u.enter()
.append('text')
.merge(u)
.text(function(d) { return d.t; })
.attr("fill","rgb(200,101,200)")
.attr('x', function(d) {
return d.x;
})
.attr('y', function(d) {
return d.y;
})
u.exit().remove();
}
Upvotes: 1
Views: 313
Reputation: 102194
A D3 simulation will start automatically. According to the documentation, d3.forceSimulation
...
Creates a new simulation with the specified array of nodes and no forces. If nodes is not specified, it defaults to the empty array. The simulator starts automatically. (emphasis mine)
The solution is stoping the simulation...
simulation.stop();
And then restarting it after the desired delay, for instance using setTimeout
:
setTimeout(function(){
simulation.restart();
},2000);
Here is the original code you're building upon with a delay of 2 seconds:
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<title>Force layout (with links)</title>
</head>
<style>
circle {
fill: cadetblue;
}
line {
stroke: #ccc;
}
text {
text-anchor: middle;
font-family: "Helvetica Neue", Helvetica, sans-serif;
fill: #666;
font-size: 16px;
}
</style>
<body>
<div id="content">
<svg width="400" height="300">
<g class="links"></g>
<g class="nodes"></g>
</svg>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script>
var width = 400,
height = 300
var nodes = [{
name: 'A'
},
{
name: 'B'
},
{
name: 'C'
},
{
name: 'D'
},
{
name: 'E'
},
{
name: 'F'
},
{
name: 'G'
},
{
name: 'H'
},
]
var links = [{
source: 0,
target: 1
},
{
source: 0,
target: 2
},
{
source: 0,
target: 3
},
{
source: 1,
target: 6
},
{
source: 3,
target: 4
},
{
source: 3,
target: 7
},
{
source: 4,
target: 5
},
{
source: 4,
target: 7
}
]
var simulation = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody().strength(-100))
.force('center', d3.forceCenter(width / 2, height / 2))
.force('link', d3.forceLink().links(links))
.on('tick', ticked)
.stop();
setTimeout(function() {
simulation.restart();
}, 2000);
function updateLinks() {
var u = d3.select('.links')
.selectAll('line')
.data(links)
u.enter()
.append('line')
.merge(u)
.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
})
u.exit().remove()
}
function updateNodes() {
u = d3.select('.nodes')
.selectAll('text')
.data(nodes)
u.enter()
.append('text')
.text(function(d) {
return d.name
})
.merge(u)
.attr('x', function(d) {
return d.x
})
.attr('y', function(d) {
return d.y
})
.attr('dy', function(d) {
return 5
})
u.exit().remove()
}
function ticked() {
updateLinks()
updateNodes()
}
</script>
</body>
</html>
Upvotes: 2