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

Google Maps Advanced Marker拖拽时位置异常问题排查求助

问题描述

在React项目中使用最新版Google Maps TS库,采用自定义SVG作为Advanced Marker。进入全屏模式拖拽该标记时,其位置会出现异常跳动,即便使用官方默认Marker也存在此问题,严重影响用户体验(UX)。相关代码如下:

export const MapAPI = ({ geolocation, setGeolocation }) => {
  const ref = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const mapOptions: google.maps.MapOptions = {
      center: { lat: geolocation.latitude, lng: geolocation.longitude },
      zoom: DEFAULT_ZOOM,
      panControl: false,
      zoomControl: false,
      mapTypeControl: false,
      scaleControl: false,
      streetViewControl: false,
      rotateControl: false,
      mapId: MAP_ID,
    };

    // we need to use async for the library load
    (async () => {
      preventMapsStyleSpread();

      const { Map } = (await google.maps.importLibrary(
        "maps"
      )) as google.maps.MapsLibrary;
      const { AdvancedMarkerElement } = (await google.maps.importLibrary(
        "marker"
      )) as google.maps.MarkerLibrary;

      const map = new Map(ref.current as HTMLElement, mapOptions);

      const draggableMarker = new AdvancedMarkerElement({
        map,
        content: mapPinSvg,
        position: { lat: geolocation.latitude, lng: geolocation.longitude },
        gmpDraggable: true,
      });

      draggableMarker.addListener("dragend", () => {
        const position = draggableMarker.position as google.maps.LatLng;
        setGeolocation({
          latitude: position.lat,
          longitude: position.lng,
          // we keep the same accuracy
          accuracy: geolocation.accuracy,
        });
      });
    })();
  }, []);

  return (
    <div
      ref={ref}
      style={{
        height: "300px",
        width: "100%",
        marginLeft: "auto",
        marginRight: "auto",
      }}
    />
  );
};

function preventMapsStyleSpread() {
  // This is to prevent Google Maps from loading Roboto
  // And fucking up the boldness of the whole application
  const head = document.getElementsByTagName("head")[0];
  const insertBefore = head.insertBefore;
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  head.insertBefore = function (newElement, referenceElement) {
    if (
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      newElement.href &&
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      newElement.href.indexOf("//fonts.googleapis.com/css?family=Roboto") > -1
    ) {
      console.info("Prevented Roboto from loading!");
      return;
    }

    insertBefore.call(head, newElement, referenceElement);
  };
}
问题分析与解决方案

这个问题并非官方Bug,而是遗漏了关键配置和状态处理逻辑,以下是核心修复点:

  • 地图容器尺寸变化未触发重绘
    进入全屏时地图容器尺寸发生改变,但Google Maps不会自动监听容器尺寸变化,导致拖拽时坐标计算偏差。需在全屏状态切换时手动调用map.resize(),让地图重新计算视图参数:

    // 在创建map实例后添加以下代码
    const handleFullscreenChange = () => {
      map.resize();
    };
    document.addEventListener('fullscreenchange', handleFullscreenChange);
    
    // 组件卸载时清理监听
    return () => {
      document.removeEventListener('fullscreenchange', handleFullscreenChange);
    };
    
  • useEffect依赖数组缺失
    当前useEffect依赖为空,不仅会导致geolocation更新时地图/标记无法同步,还可能引发 stale state 问题。修改依赖数组并补充状态同步逻辑:

    useEffect(() => {
      // ... 原有代码
    
      // 添加到async函数内部,在map和marker创建后
      if (map && draggableMarker) {
        map.setCenter({ lat: geolocation.latitude, lng: geolocation.longitude });
        draggableMarker.position = { lat: geolocation.latitude, lng: geolocation.longitude };
      }
    
      // ... 清理逻辑
    }, [geolocation]); // 更新依赖数组
    
  • 自定义SVG锚点校准(可选,但建议补充)
    虽然默认Marker也有问题,但自定义SVG若锚点设置不当会加重偏移。给AdvancedMarkerElement添加anchor属性,让标记的视觉中心点与地图坐标对齐:

    const draggableMarker = new AdvancedMarkerElement({
      map,
      content: mapPinSvg,
      position: { lat: geolocation.latitude, lng: geolocation.longitude },
      gmpDraggable: true,
      anchor: new google.maps.Point(16, 48), // 根据你的SVG实际尺寸调整(例:宽32高48的SVG,锚点设为底部中心)
    });
    

另外,preventMapsStyleSpread通过修改DOM原生方法阻止Roboto加载,可能引发潜在兼容性问题,建议改用CSS重置或Google Maps的样式隔离方案,避免修改原生DOM行为。

内容的提问来源于stack exchange,提问作者Laurent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:45:09