Reputation: 2363
I have made a grouped bubble chart using D3's force layout to create a force towards the middle, like so:
var forceStrength = 0.03;
var center = { x: widthBubbles / 2, y: heightBubbles / 2 };
var simulation = d3.forceSimulation()
.velocityDecay(0.2)
.force('x', d3.forceX().strength(forceStrength).x(center.x))
.force('y', d3.forceY().strength(forceStrength).y(center.y))
.force('charge', d3.forceManyBody().strength(charge))
.on('tick', ticked);
function charge(d) {
return -forceStrength * Math.pow(d.r, 2.0);
}
function ticked() {
bubbles
.attr('cx', function (d) { return d.x; })
.attr('cy', function (d) { return d.y; });
}
My chart looks something similar to this: Gates Foundation Educational Spending
I want to be able to apply a force on a single node when it is clicked, so that the clicked nodes will move to another area. In the documentation of D3 there is something called "positioning forces", which according to the documentation is intended to be used for multiple nodes:
While these forces can be used to position individual nodes, they are intended primarily for global forces that apply to all (or most) nodes.
So my question is if there is a way to apply forces to singles nodes in D3.
Upvotes: 2
Views: 1652
Reputation: 2363
I solved the problem by creating a function, which is called every time a bubbles is clicked:
//Function for moving bubbles when selected
function moveSelectedBubbles() {
simulation.force('x', d3.forceX().strength(forceStrength).x(function(d){
//Check if bubble is selected
return (selectedCountries.indexOf(d.data.country) >= 0) ? selectedCenter.x : center.x;
}));
simulation.alpha(1).restart();
}
But this function sets the force of every node each time a bubble is selected. Maybe there is a more efficient way to handle the case.
Upvotes: 1