我已经用react-leaflet和钩子写了一个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='&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
发布于 2021-02-24 11:38:52
在这个post中使用一些提供的旋转标记的答案,可以让它与您提供的codesandbox一起工作。默认的Marker组件没有rotationAngle或rotationOrigin作为有效的道具,你需要做一些像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时,它会更新位置(经度、经度)以及标头(旋转),因此通过将其放置在useEffect中,在下一次渲染时,Marker应已更新其位置。
我有一个codebox示例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的代码
https://stackoverflow.com/questions/66342168
复制相似问题