struggling with zoom and click

Hi!

I’m building a map using d3-geo. I’d like to the map to have three features:

  1. When the user clicks on a feature in the map, the feature’s fill color changes and properties of that feature are displayed in a div above the svg containing the map.
  2. When the user clicks on a location in the svg that is not contained by a feature, all of the features assume the same fill color, and properties of any features previously displayed in the div above the svg disappear.
  3. The map is pan-able and zoom-able (in response to the standard mouse events and gestures).

In this notebook, I’ve got #1 and #2 working (see this cell).

When I add #3 (in this cell), however, things aren’t working the way I want. Zoom and pan behave as I expect, but the response of the map to clicks isn’t what I expect. Sometimes, some of the features respond to clicks as in #1 and #2 while other features don’t. Other times, none of the features respond to clicks. I should also say that responses to clicks are what I expect until I pan and zoom. After any panning or zooming, however, the clicks don’t work anymore.

Presumably this is some sort of event propagation issue?

In case it matters, I’ve copied the code to enable panning and zooming from this cell in the collection of zoom examples.

What am I doing wrong?

Thanks!

1 Like

I’m not sure exactly what’s going on but your map click appears to be bound to the coordinates as set up on load. Thus, when you click on the SVG, it determines which region to highlight according to the original coordinates, disregarding any zoom operation that’s occurred.

Regardless, of whether that analysis is correct or not, it’s probably simpler to attach your events directly to the SVG elements themselves. Here’s a forked version that, I think, does what you want:

I’m not sure that every change I made was necessary but the key issue is the following code attached to the path elements:

.on("click", function (evt, d) {
  d3.selectAll("path").attr("class", "district");
  d3.select(this).attr("class", "selected");
  d3.select(top).select("div.info").text(d.properties.district);
  evt.stopPropagation();
});

Awesome! I don’t know why it works either…but it works!!!

For those interested in understanding what’s going on, I have a feeling that the discussion here contains the answer.

1 Like