You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用@react-google-maps/api为地图标记添加点击触发的信息提示框

使用@react-google-maps/api为标记添加点击弹出信息窗口

要实现点击标记弹出自定义信息窗口的功能,需要用到@react-google-maps/api提供的InfoWindow组件,以下是具体修改步骤:

1. 更新组件导入

在原导入语句中添加InfoWindow组件:

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

2. 扩展标记数据结构

为了让标记携带信息窗口需要展示的内容,修改MapProps接口,给otherMarkers增加标题、描述字段:

export interface MapProps {
  isMarkerShown?: boolean;
  otherMarkers?: {
    lat: number;
    lng: number;
    title: string; // 信息窗口标题
    description: string; // 信息窗口内容
  }[];
  lat: number;
  lng: number;
}

3. 添加状态管理跟踪窗口状态

在组件内部用useState记录当前选中的标记,控制信息窗口的显示/隐藏:

import { useState } from 'react';

export const Map = ({ lat, lng, isMarkerShown = true, otherMarkers }: MapProps) => {
  const [selectedMarker, setSelectedMarker] = useState<typeof otherMarkers[0] | null>(null);

  // 关闭信息窗口的通用函数
  const closeInfoWindow = () => setSelectedMarker(null);

  // 点击标记时打开对应窗口
  const handleMarkerClick = (marker: typeof otherMarkers[0]) => {
    setSelectedMarker(marker);
  };

4. 绑定事件并渲染信息窗口

修改otherMarkers的渲染逻辑,给每个标记添加点击事件,并在选中时渲染对应的InfoWindow:

{otherMarkers &&
  otherMarkers.map((marker) => (
    <React.Fragment key={`${marker.lat}-${marker.lng}`}>
      <Marker
        title={marker.title}
        position={{ lat: marker.lat, lng: marker.lng }}
        icon="/assets/svg/MapMarkerRoundedIcon.svg"
        onClick={() => handleMarkerClick(marker)}
      />
      {/* 仅当前标记被选中时显示窗口 */}
      {selectedMarker === marker && (
        <InfoWindow
          position={{ lat: marker.lat, lng: marker.lng }}
          onCloseClick={closeInfoWindow}
        >
          <div style={{ padding: '8px', minWidth: '160px' }}>
            <h3 style={{ margin: '0 0 6px 0', fontSize: '14px' }}>{marker.title}</h3>
            <p style={{ margin: 0, fontSize: '12px', color: '#555' }}>{marker.description}</p>
          </div>
        </InfoWindow>
      )}
    </React.Fragment>
  ))}

完整修改后的代码

import { useState } from 'react';
import { GoogleMap, LoadScript, Marker, InfoWindow } from '@react-google-maps/api';
import { AppConfig } from '../../../constants/AppConfig';

const containerStyle = {
  width: '100%',
  height: '100%',
};

export interface MapProps {
  isMarkerShown?: boolean;
  otherMarkers?: {
    lat: number;
    lng: number;
    title: string;
    description: string;
  }[];
  lat: number;
  lng: number;
}

export const Map = ({ lat, lng, isMarkerShown = true, otherMarkers }: MapProps) => {
  const [selectedMarker, setSelectedMarker] = useState<typeof otherMarkers[0] | null>(null);

  const closeInfoWindow = () => setSelectedMarker(null);

  const handleMarkerClick = (marker: typeof otherMarkers[0]) => {
    setSelectedMarker(marker);
  };

  return (
    <LoadScript googleMapsApiKey={AppConfig.googleMapsApiKey}>
      <GoogleMap
        options={{
          disableDefaultUI: true,
          styles: [
            { featureType: 'poi', elementType: 'labels', stylers: [{ visibility: 'off' }] },
            { featureType: 'transit', elementType: 'labels', stylers: [{ visibility: 'off' }] },
          ],
        }}
        mapContainerStyle={containerStyle}
        center={{ lat, lng }}
        zoom={15}
        onClick={closeInfoWindow} // 点击地图空白处关闭窗口
      >
        <Marker
          position={{ lat, lng }}
          visible={isMarkerShown}
          options={{}}
          icon="/assets/svg/MapMakerIcon.svg"
        />
        {/* 带信息窗口的其他标记 */}
        {otherMarkers &&
          otherMarkers.map((marker) => (
            <React.Fragment key={`${marker.lat}-${marker.lng}`}>
              <Marker
                title={marker.title}
                position={{ lat: marker.lat, lng: marker.lng }}
                icon="/assets/svg/MapMarkerRoundedIcon.svg"
                onClick={() => handleMarkerClick(marker)}
              />
              {selectedMarker === marker && (
                <InfoWindow
                  position={{ lat: marker.lat, lng: marker.lng }}
                  onCloseClick={closeInfoWindow}
                >
                  <div style={{ padding: '8px', minWidth: '160px' }}>
                    <h3 style={{ margin: '0 0 6px 0', fontSize: '14px' }}>{marker.title}</h3>
                    <p style={{ margin: 0, fontSize: '12px', color: '#555' }}>{marker.description}</p>
                  </div>
                </InfoWindow>
              )}
            </React.Fragment>
          ))}
      </GoogleMap>
    </LoadScript>
  );
};

关键说明

  • 点击标记时触发handleMarkerClick,将当前标记设为选中状态,对应的信息窗口自动显示
  • 点击信息窗口的关闭按钮或地图空白处,都会触发closeInfoWindow关闭窗口
  • 可以自定义InfoWindow内部的HTML结构和样式,匹配你需要的视觉效果

内容的提问来源于stack exchange,提问作者Michael-Liendo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:35:09