I'm trying to get coordinates of circles (cx, cy) after using d3-force collision, but I still got original positions. Are there any ways for getting translated(after collision check) coordinates of circles?
Below is just summary of code.
let data = [
{ 'x': 100, 'y': 100, 'radius': 10, cluster: 4 },
{ 'x': 100, 'y': 100, 'radius': 6, cluster: 3 },
{ 'x': 50, 'y': 200, 'radius': 10, cluster: 2 },
{ 'x': 350, 'y': 200, 'radius': 10, cluster: 2 },
{ 'x': 100, 'y': 300, 'radius': 20, cluster: 3 },
{ 'x': 100, 'y': 300, 'radius': 25, cluster: 1 },
{ 'x': 100, 'y': 300, 'radius': 33, cluster: 2 }];
var collisionForce = d3.forceCollide((d) => d.radius).strength(1).iterations(100);
var simulation = d3.forceSimulation(data).alphaDecay(0.01).force('collisionForce', collisionForce)
.force('center', d3.forceCenter(width / 2, height / 2));
var node = svg.selectAll('circle').data(data)
.enter().append('circle')
.attr('r', function (d) {
return d.radius;
}).attr('cx', function (d) {
return d.x;
}).attr('cy', function (d) {
return d.y;
})
.attr('cluster', d => d.cluster)
.attr('fill', d => that.palette[d.cluster]);
function ticked() {
node.attr('cx', function (d) {
return d.x;
})
.attr('cy', function (d) {
return d.y;
});
}
simulation.on('tick', ticked);
You can listen to the end
event on a simulation, and then access the final coordinates for the circles by changing the last line of your code to this:
simulation
.on('tick', ticked)
.on('end', () => {
d3.selectAll('circle').each(function () {
const thisD3 = d3.select(this)
console.log(thisD3.attr('cx'), thisD3.attr('cy'))
})
})
According to my knowledge, the array passed to d3.forceSimulation
edits the array in place, so you could also access the x
and y
coordinates directly in that array. The key in either case is do it when the simualtion triggers the end
event.
Hope this helps!