簡體   English   中英

如何在反應傳單中動態移動和旋轉標記?

[英]How to dynamically move and rotate marker in react-leaflet?

我用react-leaflet和 hook 編寫了一個 React 項目。 我的目標是每秒移動和旋轉標記。 但是,移動部分工作正常。 但是標記的旋轉不起作用。 最近幾天我真的被困住了。 我找不到好的解決方案。 請幫我。

map 組件如下。

import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import { useState, useEffect } from "react";
import L from 'leaflet';
import 'leaflet-marker-rotation';

const MySimpleMap = () => {
  const [lat, setLat] = useState(22.899397);
  const [lon, setLon] = useState(89.508279);
  const [heading, setHeading] = useState(30)

  useEffect(() => {
    const interval = setInterval(() => {
      myfun();
    }, 1000);
    return () => {
      clearInterval(interval);
    };
  }, [lat]);

  const defaultIcon = L.icon({
    iconUrl: "https://unpkg.com/leaflet@1.0.3/dist/images/marker-icon.png",
    iconSize: [20, 40],
    iconAnchor: [18, 18],
    popupAnchor: [0, -10],
    shadowAnchor: [10, 10]
  }); 

  const myfun = () => {    
    setLat(lat + 0.00001);
    setLon(lon + 0.00001);
    setHeading(heading+5);
    console.log("angle:" + heading);
  };
  return (
    <MapContainer className="map" center={[lat, lon]} zoom={21}>
      <TileLayer
        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <Marker position={[lat, lon]} icon={defaultIcon} rotationAngle={heading} rotationOrigin="center">
        <Popup>
          A pretty CSS3 popup. <br /> Easily customizable.
        </Popup>
      </Marker>
    </MapContainer>
  );
};

export default MySimpleMap;

完整的問題在這個沙箱中: https://codesandbox.io/s/vigilant-wood-kgv4p?file=/src/App.js

在這篇文章中使用為旋轉標記提供的一些答案,能夠使其與您提供的代碼框一起使用。 默認的Marker組件沒有rotationAnglerotationOrigin作為有效的道具,您需要執行類似 done here的操作才能獲得它。 因此,我們可以使用重用輪換代碼並將其插入到您的代碼中,方法是將其提升為可重用的 function:

const applyRotation = (marker, _options) => {
  const oldIE = L.DomUtil.TRANSFORM === "msTransform";
  const options = Object.assign(_options, { rotationOrigin: "center" });
  const { rotationAngle, rotationOrigin } = options;

  if (rotationAngle && marker) {
    marker._icon.style[L.DomUtil.TRANSFORM + "Origin"] = rotationOrigin;

    if (oldIE) {
      // for IE 9, use the 2D rotation
      marker._icon.style[L.DomUtil.TRANSFORM] = `rotate(${rotationAngle} deg)`;
    } else {
      // for modern browsers, prefer the 3D accelerated version
      marker._icon.style[
        L.DomUtil.TRANSFORM
      ] += ` rotateZ(${rotationAngle}deg)`;
    }
  }
};

然后在使用useEffect更改旋轉后調用它,因為我們還希望更新Markers position 否則旋轉將不起作用:

  useEffect(() => {
    applyRotation(markerRef.current, { rotationAngle: heading + 5 });
  }, [heading]);

當您調用myFunc時,它會更新 position(緯度,經度)以及 header(旋轉),因此通過將其放置在 useEffect 中,下一次渲染Marker應該更新其 Z4757FE07FD492A8BE0EA6A760EDD

在這里有一個代碼框示例。

上述解決方案確實存在一些問題,您需要篩選leaflet-rotatedmarker庫以獲取那些丟失的邊緣情況。 但是,如果您可以添加該庫,則更好的解決方案是導入:

import L from "leaflet";
import "leaflet-rotatedmarker";

並改用擴展的setRotationAngle

  useEffect(() => {
    if (markerRef.current) {
      markerRef.current.setRotationAngle(heading);
    }
  }, [heading]);

您還可以使用它來將其提升到RotatedMarker組件中,以便您原來的 props rotationAngle={heading} rotationOrigin="center"用例可以工作:

const RotatedMarker = forwardRef(({ children, ...props }, forwardRef) => {
  const markerRef = useRef();

  const { rotationAngle, rotationOrigin } = props;
  useEffect(() => {
    const marker = markerRef.current;
    if (marker) {
      marker.setRotationAngle(rotationAngle);
      marker.setRotationOrigin(rotationOrigin);
    }
  }, [rotationAngle, rotationOrigin]);

  return (
    <Marker
      ref={(ref) => {
        markerRef.current = ref;
        if (forwardRef) {
          forwardRef.current = ref;
        }
      }}
      {...props}
    >
      {children}
    </Marker>
  );
});

這是我測試上述內容的代碼筆

暫無
暫無

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

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