使用@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
相关产品推荐
相关产品推荐

