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

使用@vis.gl/react-google-maps添加第二个AdvancedMarker时,第一个标记的InfoWindow位置异常卡顿问题

使用@vis.gl/react-google-maps添加第二个AdvancedMarker时,第一个标记的InfoWindow位置异常卡顿问题

看起来你遇到的问题是动态添加第二个标记后,第一个标记的信息窗口(InfoWindow)和锚点标记的关联失效了,导致它“飘”在屏幕中间。这种情况一般是组件重渲染时,InfoWindow的锚点引用没正确维护,或者地图视图变化时InfoWindow没自动更新位置导致的。我给你几个实用的解决方案:

1. 抽离独立组件避免不必要的重渲染

把第一个标记和对应的InfoWindow抽成一个用React.memo包裹的单独组件,这样当动态添加第二个标记(addCustomMarker变化)时,第一个标记部分不会被强制重渲染,从而保留InfoWindow和标记的关联:

// 抽离的第一个标记组件
const LocationMarker = React.memo(({ 
  position, 
  isInfoWindowOpen, 
  onMarkerClick, 
  markerRef, 
  marker 
}) => {
  return (
    <>
      <AdvancedMarker
        ref={markerRef}
        onClick={onMarkerClick}
        position={position}
        title={'AdvancedMarker that opens an Infowindow when clicked.'}
      />
      {isInfoWindowOpen && (
        <InfoWindow
          headerDisabled
          anchor={marker}
          // 给InfoWindow加唯一key,确保位置变化时重新渲染
          key={`info-window-${position.lat}-${position.lng}`}
        >
          <label className="font-semibold text-xs">Current Location</label>
        </InfoWindow>
      )}
    </>
  );
});

// 主组件中使用该抽离组件
return (
  <APIProvider apiKey="YOUR_API_KEY">
    <Map 
      clickableIcons={false}
      mapTypeControl={false}
      streetViewControl={false}
      mapId="map-client"
      className={styles.mapContainer}
      defaultCenter={selectedCoords}
      defaultZoom={16}
      id="map-client"
      gestureHandling="cooperative"
      key={mapKey}
      onClick={(event: MapMouseEvent) => {
          if (enableAddMarker)
              setAddCustomMarker(event.detail?.latLng);
      }}
    >
      {selectedCoords && (
        <LocationMarker
          position={selectedCoords}
          isInfoWindowOpen={infoWindowOpen}
          onMarkerClick={() => setInfoWindowOpen(true)}
          markerRef={markerRef}
          marker={marker}
        />
      )}
      {/* 第二个动态标记的代码保持不变 */}
      {addCustomMarker !== null ? (
          <>
              <AdvancedMarker
                  ref={markerRef2}
                  draggable={true}
                  position={addCustomMarker}
                  onDragEnd={(e: google.maps.MapMouseEvent) => {
                      setAddCustomMarker(e.latLng?.toJSON());
                  }}
              >
                  <Pin
                      background={'#13294b'}
                      borderColor={'#13294b'}
                      glyphColor={'#D9FFFFFF '}
                  />
              </AdvancedMarker>
              {infoWindowOpen2 && (
                  <InfoWindow
                      anchor={marker2}
                      headerDisabled
                  >
                      <label className="font-semibold text-xs">New Location</label>
                  </InfoWindow>
              )}
          </>
      ) : null}
    </Map>
  </APIProvider>
);

2. 手动触发InfoWindow的位置校准

当动态添加第二个标记时,手动重置第一个InfoWindow的锚点,确保它和标记重新关联。你需要先给InfoWindow添加一个ref来获取实例:

// 主组件中添加InfoWindow的ref
const infoWindowRef = useRef<google.maps.InfoWindow>(null);

// 监听addCustomMarker的变化,重置InfoWindow锚点
useEffect(() => {
  if (infoWindowOpen && marker && infoWindowRef.current) {
    infoWindowRef.current.setAnchor(marker);
  }
}, [addCustomMarker, infoWindowOpen, marker]);

// 修改第一个InfoWindow的代码,添加ref
{infoWindowOpen && (
  <InfoWindow
    ref={infoWindowRef}
    headerDisabled
    anchor={marker}
  >
    <label className="font-semibold text-xs">Current Location</label>
  </InfoWindow>
)}

这样每次添加新标记时,都会强制把第一个InfoWindow的锚点重新指向第一个标记,修复位置偏移的问题。

3. 检查标记引用的稳定性

useAdvancedMarkerRef返回的marker实例理论上是稳定的,但如果组件重渲染过于频繁,可能会出现引用丢失的情况。你可以尝试用useMemo包裹标记的位置,减少不必要的重触发:

const stableSelectedCoords = useMemo(() => selectedCoords, [selectedCoords.lat, selectedCoords.lng]);

然后把stableSelectedCoords传给第一个AdvancedMarker的position属性,确保只有位置真正变化时才重新渲染标记。

你可以先试试第一种方案,抽离组件的方式最直接,能避免大部分重渲染导致的关联问题。如果还是不行,再结合第二种手动校准的方法。

备注:内容来源于stack exchange,提问作者Dp258

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:48:07