martin36
martin36

Reputation: 2363

D3 adding force to single node

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

Answers (1)

martin36
martin36

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

Related Questions