微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 react-leaflet 中动态移动和旋转标记?

如何解决如何在 react-leaflet 中动态移动和旋转标记?

我用 react-leaflet 和 hook 编写了一个 React 项目。我的目标是每秒移动和旋转标记。但是,移动部件工作正常。但是标记的旋转不起作用。最近几天我真的被困住了。我找不到好的解决方案。请帮帮我。

地图组件如下。

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

解决方法

在此 post 中使用一些提供的旋转标记答案,能够使其与您提供的代码和框一起使用。默认的 Marker 组件没有 rotationAnglerotationOrigin 作为有效道具,您需要执行诸如 done here 之类的操作才能获得它。因此,我们可以重用旋转代码,并将其提升为可重用的函数,从而将其插入到您的代码中:

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 位置,否则旋转将不起作用:

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

当您调用 myFunc 时,它会更新位置 (lat,lon) 以及标题(旋转),因此通过将其放置在 useEffect 中,在下一次渲染时 Marker 应该更新其位置。

我有一个代码框示例 here

上述解决方案确实存在一些问题,您需要筛选 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>
  );
});

这是我测试 above out 的代码笔

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。