Reputation: 2463
I'm trying to do a container with balls inside, attracted to the floor like gravity. I'm close to doing it well but the balls eventually melt into each other then don't preserve their visibility.
I think the problem comes from the gravity function itself because the radius of each node isn't into account:
var gravity = function() {
return function(d) {
d.y += (d.cy - d.y);
d.x += (d.cx - d.x);
};
}
or from the bounding function in the simulation animation (tick), for the same problem above
d3.selectAll("circle.node")
.attr("cx", function(d,i){ return Math.max(radius, Math.min(width - radius, d.x)); })
.attr("cy", function(d,i){ return Math.max(radius, Math.min(height - radius, d.y)); });
How can I separate each ball distinctly in this case?
Edit: i found the solution i ll share it soon
Upvotes: 2
Views: 273
Reputation: 2463
Ok, i finally read the docs and understood the problem !
All is about the collide between each node, to integrate it correctly in the forceSimulation, and the bound calculation in the tick function:
...
// Change values below to modify the physic
var simulation = d3.forceSimulation()
.velocityDecay(0.3)
.force("y", d3.forceY(height).strength(.035)) // gravity at bottom
.force("collide", d3.forceCollide().radius(radius).strength(1.5).iterations(10))
.nodes(nodes)
.on('tick', tick);
function tick() {
// bound
node.attr('cx', function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr('cy', function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
}
Upvotes: 0