reactjs - 尝试使用 react-google-maps 平滑地为标记移动设置动画

标签 reactjs use-state react-google-maps react-google-maps-api

我正在尝试像这样为我的谷歌地图标记制作动画...

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)这就是我得到的

enter image description here

还找不到setPosition函数...

最佳答案

您没有看到 setPosition 方法,因为它必须位于原型(prototype)(单击标记对象中的 [[Prototype]] 属性)。

因此您可以使用纯 js 中的任何标记动画示例(如您的回答),但我认为最好使用 requestAnimationFrame 来实现流畅的动画。我为您创建了一个简单示例,说明它如何与 @react-google-maps/api 一起使用。

https://codesandbox.io/s/google-maps-marker-animate-pos-3j78j5

如您所见,我们不应该使用 setStateforceUpdate 进行重新渲染,您可以确定您不会遇到性能问题。

我从这个答案中得到的动画标记的功能

https://stackoverflow.com/a/55043218/9058905

关于reactjs - 尝试使用 react-google-maps 平滑地为标记移动设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72262867/

相关文章:

reactjs - ts/react - useEffect 中的 fetch 被多次调用

reactjs - 在 Gorilla Mux : 403 error on POST request 中配置 CORS

reactjs - 避免双重使用效果中的陈旧状态?

javascript - 如何动态地将添加的输入值推送到数组?

javascript - 如何在谷歌地图中心制作固定标记以使用react?

javascript - 由于两个模块,Google Maps API 两次错误

javascript - react 动态添加动画反转类

reactjs - AWS Amplify ReactJS 应用程序无法重新加载页面

javascript - React 组件有时会在状态不变的情况下渲染两次

javascript - 如何使用 react-google-maps 通过点击在 map 上添加标记?