zcreativelabs / react-simple-maps

Beautiful React SVG maps with d3-geo and topojson using a declarative api.
https://www.react-simple-maps.io/
MIT License
3.04k stars 424 forks source link

onClick listener for clicking outside of map #250

Closed nicopoore closed 3 years ago

nicopoore commented 3 years ago

I apologize if this is documented somewhere, but if it is, I couldn't find it. I'm trying to use React Simple Maps in such a way that users can click on each item to select them, and they can click outside to deselect them. Currently I have set up "click to select, click again to deselect" logic, but I've found most users don't find that intuitive and try to click on the "sea" or outside the map to deselect.

I tried adding onClick listeners to components higher in the hierarchy but they overwrite the onClick listeners. I also tried creating a clickable element "behind" the map but since the map itself covers its entire boundaries and not just the SVG, the div isn't visible nor clickable.

Is there a way to achieve this, either via react-simple-maps logic itself or through workarounds?

Thanks in advance!

zimrick commented 3 years ago

Hi @nicopoore,

You're right, this is not explicitly documented anywhere. I made an example that should be able to solve your problem: https://codesandbox.io/s/click-outside-geography-to-deselect-0lu0c?file=/src/MapChart.js

The idea here is that I put a transparent rectangle behind the map in SVG and set it to the same width and height as the map itself. When this rectangle is clicked it sets the selected geography to null. It's very similar to your approach, but it uses SVG instead of the div containing the map, which as you stated does not work, since the map covers it entirely.

I hope this helps Cheers

nicopoore commented 3 years ago

Hey @zimrick, thanks so much for the quick and helpful answer. This worked, as you said I had tried the exact same thing but with a div instead of a rectangle.

Closing the issue now.

MarcoEscaleira commented 4 months ago

Hey all 👋🏼

A simple approach is to add a your onClick event to the ComposableMap component. Critically to stop the event bubbling you must add event.stopPropagation(); within your onClick of your Geography and there for it only triggers one or another.

Try it out 😄