React Google 地图标记图标未动态更新

问题描述 投票:0回答:1

我正在使用 React 和

@react-google-maps/api
开发一个送货应用程序。我有一个地图组件,它使用自定义图标显示送货人员的位置。但是,我遇到了一个问题,即当送货人员的状态发生变化(例如,从“正在送货”到“已送货”)时,标记的图标不会动态更新。

这是我的地图组件的简化版本:

import React from 'react';
import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';

const mapContainerStyle = {
  width: '800px',
  height: '600px',
};
const center = {
  lat: -34.397,
  lng: 150.644,
};
const deliveryWorkerIcon = "https://www.citypng.com/public/uploads/large/701751694974714k04h1qhze9qoibj5zsdeldgmudwiygsfhulvidozwie8c3x74fcxvb3skcj0yqfnr2xehmarxrjwct6xtqgpbryyi5giatccgmjb.png";

const MapComponent = () => {
  return (
    <LoadScript googleMapsApiKey="">
      <GoogleMap
        mapContainerStyle={mapContainerStyle}
        center={center}
        zoom={10}
      >
        <Marker
          position={center}
          icon={{
            url: deliveryWorkerIcon,
            scaledSize: new window.google.maps.Size(50, 50),
          }}
        />
      </GoogleMap>
    </LoadScript>
  );
};

export default MapComponent;

当送货员的状态更新时,标记应该会发生变化,但图标保持不变。我尝试使用

useState
根据工作人员的状态动态更新
deliveryWorkerIcon
URL,但标记不会使用新图标重新渲染。

如何确保标记图标动态更新以响应组件中的状态或道具更改?

javascript reactjs google-maps react-google-maps
1个回答
0
投票

从您提供的代码片段中,我看不到以下部分:

  • 确定当送货员的状态发生变化时如何通知您的应用程序。
  • 处理更新标记图标以响应状态变化。

要动态更改标记,您需要一种方法来侦听状态更改,然后相应地更新图标。如果您包含使用

useState
的代码部分,将会很有帮助,这样我们也可以检查任何潜在的问题。

在我的例子中,使用相同的库

(@react-google-maps/api)
,我使用
useEffect
钩子根据过期时间动态更新标记图标(我将其作为属性包含在我的标记对象中:
expirationTime
)。在效果内部,我设置了一个间隔来定期检查是否有任何标记的
expirationTime
已通过。如果是这样,图标将更新为自定义图标。

您可以在此处查看示例结果。

下面是我完整的地图组件供您检查。请记住,如何实现状态更改侦听器的具体细节将取决于您的应用程序设置,因此请将此视为指南。

import React, { useState, useRef, useCallback, useEffect } from "react";
import { GoogleMap, useLoadScript, Marker } from "@react-google-maps/api";

const mapContainerStyle = {
    width: "100wh",
    height: "100vh",
};

const center = {
    lat: -37.397,
    lng: 150.644,
};

export default function Map() {
    const { isLoaded, loadError } = useLoadScript({
        googleMapsApiKey: 'YOUR_API_KEY',
    });

    const [markers, setMarkers] = useState([]);
    const mapRef = useRef();

    // Add a marker to the map at the clicked location
    const onMapClick = useCallback((event) => {
        setMarkers((current) => [
            ...current,
            {
                lat: event.latLng.lat(),
                lng: event.latLng.lng(),
                customIcon: 'https://www.citypng.com/public/uploads/large/701751694974714k04h1qhze9qoibj5zsdeldgmudwiygsfhulvidozwie8c3x74fcxvb3skcj0yqfnr2xehmarxrjwct6xtqgpbryyi5giatccgmjb.png',
                expirationTime: new Date(Date.now() + 5000), // Expire the default icon after 5 seconds
            }
        ]);
    }, []);

    const onLoad = useCallback((map) => {
        mapRef.current = map;
    }, []);

    useEffect(() => {
        const intervalId = setInterval(() => {
            setMarkers((markers) => markers.map((marker) => {
                // If marker is expired, change its icon to the custom icon
                if (new Date() > marker.expirationTime) {
                    return { ...marker, icon: marker.customIcon };
                } else {
                    return marker;
                }
            }));
        }, 1000); // Checks if the expirationTime passes every 1 second

        return () => clearInterval(intervalId);
    }, []);

    if (loadError) return "Error loading maps";
    if (!isLoaded) return "Loading Maps";

    return (
        <GoogleMap
            mapContainerStyle={mapContainerStyle}
            zoom={8}
            center={center}
            onClick={onMapClick}
            onLoad={onLoad}
        >
            {markers.map((marker, index) => (
                <Marker
                    key={index}
                    position={{ lat: marker.lat, lng: marker.lng }}
                    icon={{ url: marker.icon, scaledSize: new window.google.maps.Size(50, 50), }}
                />
            ))}
        </GoogleMap>
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.