D3 add zoom to circle pack

2.1k views Asked by At

Is it possible to add zooming to a circle pack? Seems like it should be but mine is jumping all around the place when zoom is clicked. I've been attempting to solve this for a few days but with little success.

I've been referencing Mike's Zoomable Circle Packing block (#7607535) and nilanjenator's block (#4950148). Other examples seem to be based on these two. Here's a fiddle of my work in progress: http://jsfiddle.net/cajmcmahon/9weovdm2/5/.

From what I can make out, my layout problems lie in these two functions:

t.selectAll("circle")
        .attr("cx", function(d) {
            return x(d.x);
        })
        .attr("cy", function(d) {
            return y(d.y);
        })
        .attr("r", function(d) {
            return k * d.r;
        });

t.selectAll("text")
        .attr("x", function(d) {
            return x(d.x);
        })
        .attr("y", function(d) {
            return y(d.y);
        })
        .style("opacity", function(d) { return k * d.r > 20 ? 1 : 0; });

Also, I can't get the viz to reset (zoom out?) when I click on the background. I believe it's not getting values for 'data'...

//Reset when click on background
    d3.select(window).on("click", function(d, i) {
        zoom(data)
    });

Thanks for any help.

1

There are 1 answers

3
Cyril Cherian On BEST ANSWER

Ok both examples:

Have same output but they are implemented differently.

  1. http://bl.ocks.org/nilanjenator/4950148: This one relies on changing the cx and cy of the circle for moving and updating the radius for zoom effect.
  2. http://bl.ocks.org/mbostock/7607535: This one relies on translate to move the circles.

So in your example: you mixed both of it and thus you got a different flavor of circle packing.

You created circles and moved it into their position using translate but in the zoom section you made use of changing the cx and cy, as a result your circles flew out of the pack on zooming.

I have removed the translate and gave the cx and cy so the zoom function remain the same as what you have written.

node.append("circle")
    .attr("r", function(d) {
        return d.r;
    })
     .attr("class", function(d) { return d.children ? "parent" : "child"; })
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; })

    .on("click", function(d) { 
        zoom(node == d ? root : d); 
    });

I have changed the fiddle you gave here is a working example: http://jsfiddle.net/cyril123/khq21pgb/2/

Hope this is helpful!