簡體   English   中英

單擊 React leaflet v.3.x 中的標記時如何動態更改 map 縮放?

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

我試圖找到很多關於這個的東西,但我無法讓它發揮作用。 我想要的是當單擊標記 map 時,它會在該位置居中並得到完全縮放。 例如,我在 Unites 各州周圍共有 23 個標記,初始 map 縮放為 4。我想要的是,如果用戶單擊 map 中的標記,然后 map 中心更改為該標記的緯度、經度並放大假設從 4 到 14 . markeres 已經渲染 我不想在 function MyMapComponent 中渲染標記。 它來自 API 數據。 不知道該怎么做。 我嘗試了 useMapEvents但它適用於 map 單擊而不是標記單擊,如果我使用標記eventHandlers單擊我不能調用 map useMapEvents來設置緯度、經度和更改縮放。

這是我的代碼:

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

上面的代碼是我需要更改 map 中心和縮放

<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 子項。

帶有免費 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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM