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

基于地点自动补全片段绘制路线的实现方案及问题咨询

嘿,我来帮你梳理下实现思路,解决这个基于Place Autocomplete输入框绘制两点间路线的问题~

核心实现思路拆解

1. 分离存储起点/终点坐标

首先你得把两个输入框对应的位置信息分开存,别共用一个变量。可以定义两个全局(或者类级别的)变量,比如originLatLng和destinationLatLng,专门用来保存起点和终点的经纬度(LatLng对象)。

2. 给两个Autocomplete绑定独立的选择回调

完全不用写两个逻辑重复的addMarker方法!你可以在回调里区分当前操作的是起点还是终点输入框:

  • 初始化起点输入框的Autocomplete时,在place_changed回调里,把选中地点的坐标赋值给originLatLng,同时调用通用的addMarker方法添加起点标记;
  • 同理,终点输入框的回调里把坐标赋值给destinationLatLng,添加终点标记;
  • 每次更新完任意一个坐标后,都检查下两个坐标是否都已存在——如果都有了,就触发路线绘制逻辑。

3. 用Directions Service计算路线

Google Maps的Directions Service是计算两点间路线的核心工具,步骤很清晰:

  • 创建google.maps.DirectionsService实例;
  • 构造请求参数:包含起点、终点、出行模式(比如驾车/步行/公交等);
  • 调用route()方法发送请求,成功回调里会拿到完整的路线数据。

4. 渲染路线(两种可选方式)

方式一:用DirectionsRenderer快速渲染(推荐)

这个工具可以直接把路线渲染到地图上,还自带路线信息面板,代码量极少:

  • 创建google.maps.DirectionsRenderer实例并绑定到你的地图;
  • 在Directions Service的成功回调里,把返回的路线结果传给它的setDirections()方法即可。

方式二:手动绘制自定义Polyline

如果需要自定义路线的样式(比如颜色、宽度、透明度),可以从路线结果里提取路径点:

  • 从result.routes[0].overview_path获取简化的路线点(或者从legs[0].steps里拿详细路径);
  • 创建google.maps.Polyline实例,设置好样式属性,把路径点赋值给path,最后添加到地图上。

5. 处理重复绘制问题

每次重新选择起点/终点时,要先清除旧的路线,避免地图上叠加多条路线:

  • 如果用DirectionsRenderer,它会自动覆盖旧路线;
  • 如果用自定义Polyline,要保存Polyline实例的变量,每次绘制前调用setMap(null)清除旧路线。
核心代码片段参考
// 全局变量:地图实例、起点/终点坐标、路线服务和渲染器
let map;
let originLatLng = null;
let destinationLatLng = null;
const directionsService = new google.maps.DirectionsService();
const directionsRenderer = new google.maps.DirectionsRenderer();

function initMap() {
  // 初始化地图
  map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.7128, lng: -74.0060 }, // 默认纽约坐标,可修改
    zoom: 10,
  });
  directionsRenderer.setMap(map); // 绑定渲染器到地图

  // 初始化起点Autocomplete
  initAutocomplete("origin-input", (selectedLatLng) => {
    originLatLng = selectedLatLng;
    drawRouteIfReady();
  });

  // 初始化终点Autocomplete
  initAutocomplete("destination-input", (selectedLatLng) => {
    destinationLatLng = selectedLatLng;
    drawRouteIfReady();
  });
}

// 通用的Autocomplete初始化方法
function initAutocomplete(inputId, onPlaceSelected) {
  const input = document.getElementById(inputId);
  const autocomplete = new google.maps.places.Autocomplete(input);
  
  autocomplete.addListener("place_changed", () => {
    const place = autocomplete.getPlace();
    // 校验是否获取到有效坐标
    if (!place.geometry || !place.geometry.location) {
      alert("未找到该地址的有效坐标");
      return;
    }
    // 添加标记
    addMarker(place.geometry.location, inputId === "origin-input" ? "起点" : "终点");
    // 回调传递坐标
    onPlaceSelected(place.geometry.location);
  });
}

// 通用的添加标记方法
function addMarker(latlng, title) {
  new google.maps.Marker({
    position: latlng,
    map: map,
    title: title,
    // 可选:给起点终点设置不同图标
    // icon: title === "起点" ? "./origin-marker.png" : "./destination-marker.png"
  });
}

// 检查两点是否齐全,齐全则绘制路线
function drawRouteIfReady() {
  if (!originLatLng || !destinationLatLng) return;

  const routeRequest = {
    origin: originLatLng,
    destination: destinationLatLng,
    travelMode: google.maps.TravelMode.DRIVING // 可选DRIVING/WALKING/TRANSIT/BICYCLING
  };

  directionsService.route(routeRequest, (result, status) => {
    if (status === google.maps.DirectionsStatus.OK) {
      // 用DirectionsRenderer渲染路线
      directionsRenderer.setDirections(result);
      
      // 如果要自定义Polyline,替换上面一行:
      // const routePath = result.routes[0].overview_path;
      // const customPolyline = new google.maps.Polyline({
      //   path: routePath,
      //   strokeColor: "#FF0000",
      //   strokeOpacity: 0.8,
      //   strokeWeight: 5,
      //   map: map
      // });
    } else {
      console.error(`路线请求失败:${status}`);
      alert(`无法计算路线:${status}`);
    }
  });
}
关于你之前的疑问:共用addMarker方法为什么不行?

其实共用方法本身没问题!问题出在你没有分别存储起点和终点的坐标,也没有在每次选择地址后触发路线检查的逻辑。只要你在Autocomplete的回调里把坐标存到对应的变量,再调用drawRouteIfReady()方法,完全不需要写两个重复的addMarker~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:30:30