首页 > 解决方案 > 移动(拖动)时如何更新我的标记的新位置?使用 React 传单

问题描述

我正在使用 React-leaflet 来检索位置。我创建了一个搜索输入文本以通过 API 地址放置标记,并且我希望能够更精确地移动标记。

我已将标记设置为“draggable = true”,但我想更新 x 和 y 位置并将其显示在弹出窗口中。请问该怎么做?

import React, { useEffect, useState } from 'react'
import 'leaflet/dist/leaflet.css'
import Leaflet from "leaflet";
import L from "leaflet";
import { MapContainer, Marker, useMap, TileLayer, Popup } from 'react-leaflet'

export default function App(text: any) {
  const [x, setX] = useState(2.3522219)
  const [y, setY] = useState(48.856614)
  console.log(y, x);

  const icon = new Leaflet.DivIcon({
    className: 'custom-div-icon',
    html:
      "<div style='background-color:#c30b82;' class='marker-pin'></div><i class='material-icons'><img src='img/marker-icon.png'></i>",
    iconSize: [30, 42],
    iconAnchor: [15, 42],
    popupAnchor: [-3, -42]
  })

  function SetViewOnClick({ coords }: any) {
    const map = useMap()
    map.setView(coords, map.getZoom())

    return null
  }

  useEffect(() => {
    if (text.text) {
      setX(text.text.features[0].geometry.coordinates[0])
      setY(text.text.features[0].geometry.coordinates[1])
    }
  }, [text])

  return (
    <MapContainer
      center={[y, x]}
      attributionControl={false}
      zoomControl={false}
      zoom={12}
      style={{
        height: '350px',
        position: 'relative',
        outline: 'none',
        maxWidth: '696px',
        display: 'block',
        margin: '15px auto',
        width: '100%'
      }}
    >
      <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
      <Marker position={[y, x]} icon={icon} draggable={true}>
        <Popup>
          <span>
            {text.text
              ? text.text.query
              : "Location Default"}
          </span>
        </Popup>
        <SetViewOnClick coords={[y, x]} />
      </Marker>
    </MapContainer>
  )
}

标签: reactjsleafletreact-leaflet

解决方案


eventHandlers在 Marker comp 上与标记结合使用以ref更新 x、y。

const markerRef = useRef(null);

  const eventHandlers = useMemo(
    () => ({
      dragend() {
        const marker = markerRef.current;
        if (marker != null) {
          console.log(marker.getLatLng());
          const { lat, lng } = marker.getLatLng();
          setX(lng);
          setY(lat);
          setMarkerDragged(true);
        }
      }
    }),
    []
  );

  ...


 <Marker
    position={[y, x]}
    icon={icon}
    draggable={"true"}
    ref={markerRef}
    eventHandlers={eventHandlers}
  >
    <Popup>
      <span>{popup()}</span>
    </Popup>
    <SetViewOnClick coords={[y, x]} />
  </Marker>

您还可以使用标志在拖动标记时显示新的弹出消息,但最终取决于您如何显示弹出窗口以评估三种不同的条件。

const [markerDragged, setMarkerDragged] = useState(false);
  const popup = () => {
    if (markerDragged) return `New latitude: ${y}, new longitude: ${x}`;
    return text ? text.query : "Location Default";
  };

演示


推荐阅读