单击 React 传单 v.3.x 中的标记时如何动态更改地图缩放?

How to change map zoom dynamically when clicking on a marker in react leaflet v.3.x?

我试图找到很多与此相关的东西,但我无法让它发挥作用。我想要的是当单击标记地图时在该位置获得中心并获得完全缩放。例如,我在美国各州周围共有 23 个标记,初始地图缩放比例为 4。我想要的是,如果用户单击地图中的标记,然后地图中心更改为该标记的纬度、经度并放大假设从 4 到 14 . markeres 已经渲染 我不希望标记在函数 MyMapComponent 中渲染。它来自 API 数据。不知道该怎么做。我尝试了 useMapEvents 但它适用于地图点击而不是标记点击,如果我使用标记 eventHandlers 点击我无法调用地图 使用 MapEvents 设置纬度、经度和更改缩放比例。

这是我的代码:

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

以上代码是我需要更改地图中心和缩放

<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>

有什么办法可以做到这一点吗?

你应该在 Marker 上使用 eventHandlers 属性并监听点击事件。然后使用本机传单的代码: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>
      );
    })
  );
}

然后使用 Markers comp 作为 MapContainer child。

Demo with a free api

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;