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

使用Google Maps API显示两点路线时地图抖动,如何修复?

解决Google Maps API地图缩放/切换时频繁重置到初始位置的问题

问题根源

  1. 固定坐标与视野调整冲突:你给GoogleMap设置了固定的center={positionA}和zoom={10},但同时在onLoad回调里调用fitBounds把视野调整到包含两个坐标的范围。每次组件重渲染时,地图会先跳到固定的初始位置,再被fitBounds拉回,导致抖动。
  2. 路线服务重复触发:DirectionsService直接嵌套在GoogleMap的JSX中,每次组件重渲染(比如directions状态更新)都会重新创建服务实例、发起重复请求,触发状态更新后再次重渲染,加剧地图重置问题。

修复方案

1. 移除固定的center和zoom属性

让地图通过fitBounds或DirectionsRenderer自动控制视野,避免手动设置的初始位置干扰。

2. 用useEffect控制路线请求时机

把路线请求逻辑移到useEffect中,只在组件初始化或位置坐标变化时发起一次请求,避免重复触发。

3. 补全缺失的React钩子导入

原代码中使用了useState和Fragment但未导入,需要补上。

修改后的完整代码

import { GoogleMap, useLoadScript, DirectionsRenderer } from '@react-google-maps/api';
import { Marker } from '@react-google-maps/api';
import { useState, useEffect, Fragment } from 'react'; // 补全导入

const libraries = ['places'];

export default function Details() {
  const positionA = { lat: 41.8781, lng: -87.6298 };
  const positionB = { lat: 42.8781, lng: -88.6298 };

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

  const [directions, setDirections] = useState(null);

  const { isLoaded, loadError } = useLoadScript({
    googleMapsApiKey: process.env.NEXT_PUBLIC_GMAPS_API_KEY,
    libraries,
  });

  // 仅在地图加载完成后发起一次路线请求
  useEffect(() => {
    if (!isLoaded) return;

    const directionsService = new window.google.maps.DirectionsService();
    directionsService.route(
      {
        destination: positionB,
        origin: positionA,
        travelMode: 'DRIVING',
      },
      (response) => {
        if (response.status === 'OK') {
          setDirections(response);
        } else {
          console.log('Directions request failed due to: ' + response.status);
        }
      }
    );
  }, [isLoaded]);

  if (loadError) return "Error loading maps";

  return (
    <Fragment>
      <section className="contact-container">
        <div className="detail-slot">
          <div style={{ height: "calc(100% - 16rem)" }}>
            {isLoaded && (
              <GoogleMap
                mapContainerStyle={containerStyle}
                // 移除固定的center和zoom
                onLoad={(map) => {
                  const bounds = new window.google.maps.LatLngBounds();
                  bounds.extend(positionA);
                  bounds.extend(positionB);
                  map.fitBounds(bounds);
                }}
              >
                {positionA && <Marker position={positionA} />}
                {positionB && <Marker position={positionB} />}
                
                {directions && (
                  <DirectionsRenderer
                    directions={directions}
                    options={{
                      polylineOptions: {
                        strokeColor: 'red',
                      },
                    }}
                  />
                )}
              </GoogleMap>
            )}
          </div>
        </div>
      </section>
    </Fragment>
  );
}

额外说明

  • 移除固定坐标后,地图会先通过onLoad的fitBounds定位到包含两个坐标的范围,当DirectionsRenderer加载路线后,会自动调整视野覆盖整条路线,不会再出现重置抖动。
  • 使用useEffect封装路线请求,确保仅在地图加载完成后发起一次请求,避免重复触发状态更新导致的组件重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:15:22