Question

I'm having a problem in getting D3 to perform proper brushing when zooming is performed.

I have a jsFiddle created here http://jsfiddle.net/Gwp25/2/ showing the network with some dummy data I found elsewhere. The operation to follow is this. Zoom in (using mousewheel), then turn on brushing. After doing this, brush the nodes. The nodes that are selected are off - some out of the brush area. Here is the relevant part of the code dealing with the selecting of nodes within the brush extent.

            .on("brush", function() {
                var extent = d3.event.target.extent();
                console.log(extent);
                d3.selectAll(".node").select("circle").classed("selected", function(d) {
                    return d.selected = (extent[0][0] <= x_scale(d.x) && x_scale(d.x) < extent[1][0]
                            && extent[0][1] <= d3.tran(d.y) && y_scale(d.y) < extent[1][1]);
                });
            })

Does anyone have an idea to fix this. I know it's to do with the nodes and their original position and x, but I'm not quite sure about how to get the node x and y with respect to their zoomed location.

Any ideas?

Was it helpful?

Solution

I believe I have a working version of what you're looking for: http://jsfiddle.net/Gwp25/8/

You were close on the implementation. I'll explain what I changed to make it work.

First, I attached scales to the zoom function. This is important as d3 will automatically update them as you zoom in and out. It's important to note that I did not use your identity scales. If you use an identity scale d3 zoom behavior will not update the scale. Here are the scales that I created that are identical to yours when there is no zoom:

var x_scale = d3.scale.linear().domain([0, chartWidth]).range([0, chartWidth]);
var y_scale = d3.scale.linear().domain([0, chartHeight]).range([0, chartHeight]);

Now the brush also takes scales as parameters. This is where you mistakenly put the original identity scales. So even though the graph was zoomed and panned you used the same scale to map points to the newly zoomed graph.

In order to feed the brush the correct scales, you can access the zoom behavior's scales by calling: zoom.x() or zoom.y().

Once you've done this the rest is gravy.

Note: I hacked the code a bit so I could access your zoom function in toggleBrushing by making it a global variable. I don't recommend keeping it this way, but I didn't want to do heavy refactoring. Good luck, hope that helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top