首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在react-leaflet中动态移动和旋转标记?

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

Stack Overflow用户
提问于 2021-02-24 06:43:51
回答 1查看 1.2K关注 0票数 3

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

map组件如下所示。

代码语言:javascript
复制
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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-24 11:38:52

在这个post中使用一些提供的旋转标记的答案,可以让它与您提供的codesandbox一起工作。默认的Marker组件没有rotationAnglerotationOrigin作为有效的道具,你需要做一些像done here这样的事情来获得它。因此,我们可以使用重用循环代码,并通过将其提升为可重用函数来将其插入到您的代码中:

代码语言:javascript
复制
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位置,否则旋转将不起作用:

代码语言:javascript
复制
  useEffect(() => {
    applyRotation(markerRef.current, { rotationAngle: heading + 5 });
  }, [heading]);

调用myFunc时,它会更新位置(经度、经度)以及标头(旋转),因此通过将其放置在useEffect中,在下一次渲染时,Marker应已更新其位置。

我有一个codebox示例here

上面的解决方案确实有一些问题,你需要在leaflet-rotatedmarker库中筛选,以获得那些丢失的边缘案例。但是,如果您可以添加该库,则更好的解决方案是导入该库:

代码语言:javascript
复制
import L from "leaflet";
import "leaflet-rotatedmarker";

并改为使用扩展的setRotationAngle

代码语言:javascript
复制
  useEffect(() => {
    if (markerRef.current) {
      markerRef.current.setRotationAngle(heading);
    }
  }, [heading]);

您还可以使用它将其提升到RotatedMarker组件中,以便您最初的props rotationAngle={heading} rotationOrigin="center"用例可以工作:

代码语言:javascript
复制
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的代码

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66342168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档