簡體   English   中英

嘗試使用 react-google-maps 平滑地為標記移動設置動畫

[英]Trying to animate markers movement with react-google-maps smoothly

我正在嘗試像這樣為我的谷歌地圖標記設置動畫......

標記動畫運動示例

我試圖將此代碼復制到反應中(使用@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

在谷歌地圖文檔中,您通常使用函數 setPosition 來更新標記的位置,問題是,如果我使用 react-google-maps/api 為了避免 setState 問題?

好吧,我嘗試使用 useRef 掛鈎,像這樣訪問<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]] 屬性)。

因此,您可以使用純 js 中的任何標記動畫示例(如您的答案),但我認為最好使用requestAnimationFrame進行平滑動畫。 我為您創建了一個簡單的示例,它將如何與@react-google-maps/api一起使用。

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

如您所見,我們不應該使用setStateforceUpdate進行渲染,您可以確定您不會遇到性能問題。

我從這個答案中獲取的動畫標記的功能

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

您可以使用 reducer 強制渲染

const [, forceUpdate] = useReducer(x => x + 1, 0);

在你設置的超時結束時添加這個

setTimeout(() => {
setMarkerMotion((prev) => ({
YOUR OLD CODE HERE
forceUpdate();
 }, delay);

這將強制組件每次渲染

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM