6

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?

VividD
  • 10,456
  • 6
  • 64
  • 111
Eamonn
  • 597
  • 7
  • 23
  • Even though you're accounting for the scale when you're drawing your brush, your top-left coordinate of your mouse selection (for the brush) no longer matches with the top-left coordinate of your canvas, which has been zoomed out of view. You're also not accounting for the scale in translating, which is why when you're zoomed in it drags so slowly. – Elijah Jan 03 '14 at 01:33
  • Do you mean for the node? I just modified this to node.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")scale(" + scale_val + ")"; }); but it doesn't aid things at all. I didwant to solve that issue with panning, it's a bit annoying being so slow and I thought there was a problem with the scale since it resets itself when I use the slider I've implemented to help in zooming. Any idea on how I get the corrected value for the top-left in D3? – Eamonn Jan 03 '14 at 01:45
  • http://jsfiddle.net/Gwp25/4/ - this is with the scale added. – Eamonn Jan 03 '14 at 01:50
  • Have you seen [this example](http://bl.ocks.org/zrlram/2522963)? – Lars Kotthoff Jan 03 '14 at 11:09
  • Thanks Lars, but brushing isn't the problem. It's mixing that with zooming which is the issue and sorting out the problems that come from having different offsets, zoom levels and so forth. If you try the example in my jsFiddle, you'll be able to brush fine at the initial level. However, if switch the brushing off, zoom in (using the mouse wheel) and then switch brushing back on again, you'll notice that the selected nodes aren't correct. – Eamonn Jan 03 '14 at 16:23

1 Answers1

3

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!

Ben Rudolph
  • 2,509
  • 2
  • 19
  • 26
  • Thank you for the explanation and help! I still appear to be struggling a bit with scales. I had to hack a way of getting the code online just to illustrate the problem. The implementation is more structured in my codebase. The other thing I don't quite get is the stuttering effect when panning. @Elijah mentioned that I'm not accounting for the scale when translating on zoom. I think I am in the implementation at the minute, but there's obviously something amiss. Any ideas on that? Then I'm there I think. – Eamonn Jan 04 '14 at 17:14
  • Hmm, the jittering is a bit puzzling. I'll think about it; on first glance I'm not sure what the issue is there. – Ben Rudolph Jan 04 '14 at 19:57