简体   繁体   English

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

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

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.我想要的是当单击标记 map 时,它会在该位置居中并得到完全缩放。 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.例如,我在 Unites 各州周围共有 23 个标记,初始 map 缩放为 4。我想要的是,如果用户单击 map 中的标记,然后 map 中心更改为该标记的纬度、经度并放大假设从 4 到 14 . markeres 已经渲染 我不想在 function MyMapComponent 中渲染标记。 it come from API data.它来自 API 数据。 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.我尝试了 useMapEvents但它适用于 map 单击而不是标记单击,如果我使用标记eventHandlers单击我不能调用 map useMapEvents来设置纬度、经度和更改缩放。

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上面的代码是我需要更改 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>

is there any way to accomplish this?有什么办法可以做到这一点?

You should use eventHandlers prop on Marker and listen to click event.您应该在 Marker 上使用eventHandlers道具并收听点击事件。 Then use native leaflet's code: map.setView(coords, zoom)然后使用原生传单的代码: 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.然后将 Markers comp 用作 MapContainer 子项。

Demo with a free api 带有免费 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