WoltjerD
WoltjerD

Reputation: 463

d3 force directed graph nodes stay at fixed position after filter

In my d3 force directed scatter plot i try to make points disappear and re-appear by clicking on a legend key. After clicking the legend key, i would like the remaining points to regroup and not to stay fixed in the same position, leaving blank spaces (screenshots). When clicking again on the legend, they should fly in again.

I tried to remove the fill of the circles upon clicking on a legend key, which is working, but obviouly does not make the force do its work..

My code on blockbuilder.org: http://blockbuilder.org/dwoltjer/04a84646720e1f82c16536d5ef9848e8 beforeblank spaces remain after clicking purple legend key

Upvotes: 1

Views: 631

Answers (2)

Marcelo
Marcelo

Reputation: 4282

You can treat the filtered data as new data and apply the update, enter and exit pattern:

   var node = svg.selectAll(".dot")
      .data(data);

   node.exit().remove();


   node.enter().append("circle") 
      .attr("class", "dot")
      .attr("r", radius)
   ......

The click event for legend:

  legend.append("rect")
        .attr("x", width - 18)
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", color)
        .on("click", function (d) {

                        visible[d] = !visible[d];
                        var newdata = data.filter(function(e) { return visible[e.bank];});

                        DrawNode(newdata);

        });

Here is the update blocks

Upvotes: 2

Oliver Houston
Oliver Houston

Reputation: 323

Simply deleting the nodes should be enough to make the force rearrange itself and group the nodes again. But, you will want to save the nodes to bring them back (possibly using a temporary array).

However, if you want the nodes to fly off screen (and back on), then what I'd do (using V4) is move the nodes to a new forcePoint that's way off screen:

 legend.append("rect")
    .attr("x", width - 18)
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", color)
    .on("click", function (d) {
      node.filter(function () {
           return this.dataset.bank === d;
           })
            position
           .force('x', d3.forceX(width/2).strength(20))
           .force('y', d3.forceY(height*2).strength(20));//should be twice the height of the svg, so way off the y axis. Or whichever direction you choose.
     });

Upvotes: 2

Related Questions