我正在尝试像这样为我的谷歌地图标记制作动画...
Example of markers animated movement
我尝试将此代码复制到 React 中(使用 @react-google-maps/api),但无法使其正常工作,我遇到了多个问题,第一,我是使用 useState 保存移动,但是,由于我必须多次快速更新此数据,这可能会导致我的组件出现实际问题,因为不建议在 for 循环内或通常以毫秒为单位多次调用 seState。
到目前为止,这是我的代码(关注 useEffect 和 makeMarkerMove 函数)
interface IProps {
resourceData: IResourceMarkers;
}
interface ICustomGeo {
lat: number;
lng: number;
}
interface ICustomMovement {
newPosition: ICustomGeo;
}
const ResourceMarkersHero: FC<IProps> = ({
resourceData: {
g: {
geopoint: { _lat, _long },
},
},
}) => {
const [selectedMarker, setSelectedMarker] = useState<boolean>(false);
const [markerMotion, setMarkerMotion] = useState<ICustomMovement>({
newPosition: { lat: _lat, lng: _long },
});
const makeMarkerMove = () => {
const delay = 10;
const speed = 100; // how fast will the marker move
const deltaLat = (_lat - markerMotion.newPosition.lat) / speed;
const deltaLng = (_long - markerMotion.newPosition.lng) / speed;
for (let i = 0; i <= 100; i++) {
const newLat = markerMotion.newPosition.lat + deltaLat;
const newLng = markerMotion.newPosition.lng + deltaLng;
setTimeout(() => {
setMarkerMotion((prev) => ({
...prev,
newPosition: {
...prev.newPosition,
lat: newLat,
lng: newLng,
},
}));
}, delay);
}
};
useEffect(() => {
if (_lat !== markerMotion.newPosition.lat) makeMarkerMove();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [_lat, _long]);
return (
<>
{disponibilidad && (
<Marker
position={markerMotion.newPosition}
>
</Marker>
)}
</>
);
};
export default ResourceMarkersHero;
我写的代码没有更新状态,那么,我怎样才能顺利地为我的标记制作动画,就像在前面的例子中一样,我怎样才能改变我的代码来让它工作。
提前致谢!
重要更新 1.0
在 google maps 文档中,您通常使用函数 setPosition 来更新标记的位置,问题是,如果我使用 react-google-maps/api,我将如何在 react 中访问该函数为了避免 setState 问题?
好吧,我尝试使用 useRef 钩子(Hook)来访问 <Marker />
像这样的组件。
const ResourceMarkersHero: FC<IProps> = ({
resourceData: {
codigo_tipo_vehiculo,
g: {
geopoint: { _lat, _long },
},
identificacion,
nombre,
disponibilidad,
equipo,
telefono,
},
}) => {
const [selectedMarker, setSelectedMarker] = useState<boolean>(false);
const [markerMotion, setMarkerMotion] = useState<ICustomMovement>({
newPosition: { lat: _lat, lng: _long },
});
const markerRef = useRef() as RefObject<Marker>;
console.log(markerRef.current);
const makeMarkerMove = () => {
const delay = 10;
const speed = 100; // how fast will the marker move
const deltaLat = (_lat - markerMotion.newPosition.lat) / speed;
const deltaLng = (_long - markerMotion.newPosition.lng) / speed;
for (let i = 0; i <= 100; i++) {
const newLat = markerMotion.newPosition.lat + deltaLat;
const newLng = markerMotion.newPosition.lng + deltaLng;
setTimeout(() => {
setMarkerMotion((prev) => ({
...prev,
newPosition: {
...prev.newPosition,
lat: newLat,
lng: newLng,
},
}));
}, delay);
}
};
useEffect(() => {
if (_lat !== markerMotion.newPosition.lat) makeMarkerMove();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [_lat, _long]);
return (
<>
{disponibilidad && (
<Marker
onClick={() => setSelectedMarker(!selectedMarker)}
position={markerMotion.newPosition}
ref={markerRef}
>
{selectedMarker && (
<InfoWindow onCloseClick={() => setSelectedMarker(false)}>
<ResourceMarkersModal
identificacion={identificacion}
nombre={nombre}
equipo={equipo}
telefono={telefono}
/>
</InfoWindow>
)}
</Marker>
)}
</>
);
};
export default ResourceMarkersHero;
但是,当我 console.log(markerRef.current)
这就是我得到的
还找不到setPosition函数...
最佳答案
您没有看到 setPosition
方法,因为它必须位于原型(prototype)(单击标记对象中的 [[Prototype]] 属性)。
因此您可以使用纯 js 中的任何标记动画示例(如您的回答),但我认为最好使用 requestAnimationFrame
来实现流畅的动画。我为您创建了一个简单示例,说明它如何与 @react-google-maps/api
一起使用。
https://codesandbox.io/s/google-maps-marker-animate-pos-3j78j5
如您所见,我们不应该使用 setState
或 forceUpdate
进行重新渲染,您可以确定您不会遇到性能问题。
我从这个答案中得到的动画标记的功能
关于reactjs - 尝试使用 react-google-maps 平滑地为标记移动设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72262867/