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.07k stars 424 forks source link

Markers Size is changing on zoom in and zoom out #188

Open prathyusha311 opened 4 years ago

prathyusha311 commented 4 years ago

Hi Currently, On Zoom-in and Zoom-out, Marker size is changing accordingly. Is there a way to keep the marker size fixed, i.e it shouldn't change its size on zoom-in and zoom-out.

zimrick commented 4 years ago

It's not well documented at the moment, but you can achieve this by using the useZoomPan hook. This is the same hook that react simple maps uses under the hood for the ZoomableGroup component. You can make a completely custom zoomable group and use the position object to resize markers based on zoom.

Here's an example of this: https://codesandbox.io/s/custom-zoomablegroup-iqtwj

lostfictions commented 4 years ago

Would love to see this documented and <CustomZoomableGroup> added to this library -- I think this was previously easy to achieve with the <Markers> component, but the equivalent functionality simply doesn't exist anymore.

Also, MapContext isn't exposed to consumers of this package so anyone reimplementing a <CustomZoomableGroup> can't use it like it's used in <ZoomableGroup> itself:

https://github.com/zcreativelabs/react-simple-maps/blob/a0004e4ad0a15644c0ce466c8edf1d69279935ca/src/components/ZoomableGroup.js#L21

kopach commented 3 years ago

Hi there. In version 2.3.0 onMove event is available https://github.com/zcreativelabs/react-simple-maps/blob/master/src/components/useZoomPan.js#L51 which exposes scale factor as property k. So it's now possible to implement this feature quite easily without need of CustomZoomableGroup in few lines of code:

const [scaleFactor, setScaleFactor] = useState(1);
//...
<ZoomableGroup onMove={({ k }) => setScaleFactor(k)}>
//...
<circle r={12 / scaleFactor} fill="#F53" />

See working example here

https://codesandbox.io/s/react-simple-maps-do-not-change-markers-size-on-zoom-cwstb?file=/package.json

See also docs here: https://www.react-simple-maps.io/docs/zoomable-group/

I believe the issue can be closed now

kopach commented 3 years ago

Going forward, some hook like this one could be created and re-used across app

export function useStaticMapMarkerSize(
  markerRadius: number,
  initialMapScaleFactor: number = 1
): [number, (scaleFactor: number) => void] {
  const [scaleFactor, setScaleFactor] = useState<number>(initialMapScaleFactor)
  const scaledRadius = markerRadius / (scaleFactor - initialMapScaleFactor + 1)

  return [scaledRadius, setScaleFactor]
}

and later in code

  const initialScaleFactor = 1.4
  const [scaledMarkerRadius, setScaleFactor] = useStaticMapMarkerSize(markerRadius, initialScaleFactor)

  //..
  <ZoomableGroup
    zoom={initialScaleFactor}
    onMove={({ k }: { k: number }): void => setScaleFactor(k)}
  >
    // ..
    {markers.map(({ name, coordinates, status }) => (
      <Marker key={coordinates.toString()} coordinates={coordinates}>
        <circle r={scaledMarkerRadius} />
      </Marker>
    ))}
  </ZoomableGroup>
AstaDK commented 2 years ago

I used demo custom marker here: https://www.react-simple-maps.io/examples/custom-markers/ And when I zoom in on the map chart then I see that the marker with custom is not able to scale. With marker is a <circle/> tag is easer to scale with property r as <circle r={12 / scaleFactor} fill="#F53" /> but when I used <path/> tag and how can I scale it to match with chart

arquilca commented 2 years ago

tom m

You can try scaling the corresponding attributes that modify the custom marker's position/size. On the element it would be something like: transform={translate(${-8 / scaleFactor}, ${-20 / scaleFactor}), scale(${.7 / scaleFactor})}

drecloud commented 2 years ago

On a similar note, how do we make the marker stay at the coordinate as you zoom in/pan?

arquilca commented 2 years ago

On a similar note, how do we make the marker stay at the coordinate as you zoom in/pan?

I think that's what the translate portion of the transform is for.