0

i tried to find many things regards this but i can't make it work. what i want is when click on marker map got center on that location and got full zoom. for example i have total 23 markers on all around Unites states and initial map zoom is 4. what i want is if user click on marker in map then map center change to that marker lat, lng and got zoom in for suppose to 14 from 4. markeres are render already i don't want markers renders in function MyMapComponent. it come from API data. there is no clue how to do. i tried useMapEvents but it works on map click not marker click and if i use markers eventHandlers click i can't call map useMapEvents to set lat, lng and change zoom.

Here is my code:

function MyMapComponent() {
const map = useMapEvents({
    click: () => {
        let data = {lat: 46.8835319, lng: -114.0348327}
        map.flyTo(data, 18)
    }
})  
return null}

above code is i need to change map center and zoom

<div className="project-view-section">
                <MapContainer bounds={outerBounds} center={[37.2755, -104.6571]} zoom={mapOptions.zoom} scrollWheelZoom={false}>
                    <MyMapComponent />
                    <LayersControl position="topright">
                        <LayersControl.BaseLayer checked name="Mapbox Satellite">
                            <TileLayer
                                url={'https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/256/{z}/{x}/{y}@2x?access_token='+MAPBOX_TOKEN}
                                attribution="Map data &copy; <a href=&quot;https://www.mapbox.com/&quot;>Mapbox</a>"
                            />
                        </LayersControl.BaseLayer>
                        <LayersControl.BaseLayer name="Mapbox Streets">
                            <TileLayer
                                url={'https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}@2x?access_token='+MAPBOX_TOKEN}
                                attribution="Map data &copy; <a href=&quot;https://www.mapbox.com/&quot;>Mapbox</a>"
                            />
                        </LayersControl.BaseLayer>
                    </LayersControl>
                    <MarkerClusterGroup>
                    {   
                        
                            state.markersData.map((element, index) =>
                                <Marker 
                                    key={index} 
                                    marker_index={index} 
                                    position={element} 
                                    icon={icon} 
                                    eventHandlers={{click: () => {test()},}}>
                                </Marker>
                            )
                        
                    }
                    </MarkerClusterGroup>

                </MapContainer>
            </div>

is there any way to accomplish this?

2 Answers 2

2

You should use eventHandlers prop on Marker and listen to click event. Then use native leaflet's code: map.setView(coords, zoom)

function Markers({ data }) {
  const map = useMap();
  return (
    data.length > 0 &&
    data.map((marker, index) => {
      return (
        <Marker
          eventHandlers={{
            click: () => {
              map.setView(
                [
                  marker.geometry.coordinates[1],
                  marker.geometry.coordinates[0]
                ],
                14
              );
            }
          }}
          key={index}
          position={{
            lat: marker.geometry.coordinates[1], // your api structure
            lng: marker.geometry.coordinates[0] // your api structure
          }}
          icon={icon}
        >
          <Popup>
            <span>{marker.properties.label}</span>
          </Popup>
        </Marker>
      );
    })
  );
}

Use Markers comp as a MapContainer child then.

Demo with a free api

0
0
import React, { useState, useRef, useEffect } from 'react';
import {
  MapContainer,
  Marker,
  Popup,
  TileLayer,
  useMap
} from 'react-leaflet';
import L from 'leaflet';
import { v4 as uuidv4 } from 'uuid';

import 'leaflet/dist/leaflet.css';
import { useTranslation } from 'react-i18next';

const iconMarker = new L.Icon({
  iconUrl: require('../assets/images/loc.png'),
  iconAnchor: [25, 50],
  popupAnchor: [0, -30],
  iconSize: new L.Point(50, 50),
});

function Markers({ data, isActive }) {
  const map = useMap();
  const [refReady, setRefReady] = useState(false);
  let popupRef = useRef();
  useEffect(() => {
    if (refReady && isActive) {
      popupRef.addTo(map);
    }
  }, [isActive, refReady, map]);
  return (
    data.length > 0 &&
    data.map((marker, index) => {
      return (
        <Marker
          key={index}
          eventHandlers={{
            click: () => {
              map.setView([marker.latitude, marker.longitude], 16);
            },
          }}
          position={{
            lat: marker.latitude,
            lng: marker.longitude,
          }}
          icon={iconMarker}
        >
          <Popup
            ref={(r) => {
              popupRef = r;
              setRefReady(true);
            }}
          >
            <span>{marker.name}</span>
          </Popup>
        </Marker>
      );
    })
  );
}

const Map = ({ devices }) => {
  const { t } = useTranslation();
  const locationLati = [devices?.map((location) => location.latitude)];
  const latitudeList = [...locationLati[0]];
  const locationLongi = [devices?.map((location) => location.longitude)];
  const longitudeList = [...locationLongi[0]];
  let positionCurrent = [latitudeList[0], longitudeList[0]];
  const newDevice = [...devices].reverse();
 

  return (
    <MapContainer
      center={[0,0]}
      zoom={12}

      markerZoomAnimation={true}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
    

      <Markers data={newDevice} isActive />
    </MapContainer>
  );
};

export default Map;
1
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Apr 14, 2022 at 18:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.