Anis CHAHED
Anis CHAHED

Reputation: 11

How can I make Markers appear on a map when I zoom on it with Hooks

I'm relatively new to frontend developement and I have issues finding the right documentations to help me with this feature. I've been trying to make some markers appear when zooming to a certain level using react-leaflet and React Hooks.

Here is my code for the map:

import React, { useEffect } from 'react'; 
import { MapContainer, TileLayer, LayerGroup, Marker } from 'react-leaflet';
import TanitMarker from './marker';
import ZoomControlledLayer from './zoom-controlled-layer';
import CustomPopup from './popup';
import './my-map.scss';

function MyMap() {

  const hotel = {
    thumbnail: {
      src: "./hotel.jpg"
    },
    name: "",
    title: "****",
  }

  useEffect(() => {
    console.log('Map is mounted!');
  }, []); 


  return (
    <div className="map-container">
      <MapContainer center={[35.741728, 10.626254]} zoom={8} scrollWheelZoom={true}>
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <ZoomControlledLayer zoomRef={7}>
          <LayerGroup>
            <Marker position={[36.4242, 10.6749]}
              riseOnHover={true}>
              <CustomPopup site={hotel}></CustomPopup>
            </Marker>
          </LayerGroup>
        </ZoomControlledLayer>
      </MapContainer>
    </div>
  )
}

export default MyMap;

I'm trying to make the LayerGroup under ZoomControlledLayer to appear when zoom level 7 is reached.

Thank you in advance.

Upvotes: 1

Views: 950

Answers (1)

Seth Lutske
Seth Lutske

Reputation: 10676

TileLayers and GridLayers have a maxZoom and minZoom property, but it doesn't look like a LayerGroup has one, so you'll have to implement it manually. First, let's keep track of the map's zoom level in a state variable:

import { MapContainer, useMapEvents } from 'react-leaflet';

function ZoomTracker = ({ setZoom }) => {
  const map = useMapEvents({
    zoom(){
      setZoom(map.getZoom())
    }
  })
  return null
}

function MyMap(){

  const [zoom, setZoom] = useState()

  return (

    <MapContainer>
      <ZoomTracker setZoom={setZoom} />
      <ZoomControlledLayer zoom={zoom} minZoom={7}>
        {...all_the_stuff_in_here}
      </ZoomControlledLayer>
    </MapContainer>

  )

}

So now MyMap is keeping track of the current zoom level in state, and passing it to the ZoomControlledLayer component. Now in your ZoomControlledLayer:

const ZoomControlledLayer = ({ zoom, minZoom, children }) => {

  if (zoom >= minZoom){
    return (
      <>
        {children}
      </>
    );
  } else {
    return null;
  }

}

So ZoomControlledLayer only renders anything when the maps zoom is the same or greater as your minZoom. I haven't tested this, but hopefully its enough to get you going. You can read more about using map events in react-leaflet v3 here.

Upvotes: 3

Related Questions