【问题标题】:calculate distance and show route on google map with waypoints使用航点计算距离并在谷歌地图上显示路线
【发布时间】:2026-01-02 07:00:01
【问题描述】:

我正在开发一个网络应用程序,我需要在其中添加取货地址、下车地址和一系列访问区域,用户将通过这些访问区域在取货地址和下车地址之间移动。我所做的是路由地图并计算接送地址之间的距离,但我无法将访问区域与接送地址相匹配。 这是我的代码,如果有人可以告诉我如何做到这一点:

网络表单

<form class="uk-form" name="myForm" id="myForm">
<input id="pickup" class="controls" name="pickup" type="text"/>
<input id="dropoff" class="controls" name="dropoff" type="text"/>
<input id="visitarea" class="controls" name="visitarea" type="text"/>    
<input id="calculatefare" class="calculatefare" type="button" value="Calculate Fare" />
</form>

Javascript 函数

function initAutocomplete() {

var origin_place_id = null;
var destination_place_id = null;
var visitarea_place_id = null;

var travel_mode = google.maps.TravelMode.DRIVING;

var map = new google.maps.Map(document.getElementById('map-canvas'), {
  mapTypeControl: false,
  center: {lat: 30.3753, lng: 69.3451},
  zoom: 7,
  scrollwheel: false,
    navigationControl: false,
    mapTypeControl: false,
    scaleControl: false
});

var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer;
directionsDisplay.setMap(map);

var pickup = document.getElementById('pickup');
var dropoff = document.getElementById('dropoff');
var visitarea = document.getElementById('visitarea');


var options = {
componentRestrictions: {country: 'pk'}//Pakistan only
};

var origin_autocomplete = new google.maps.places.Autocomplete(pickup,options);
origin_autocomplete.bindTo('bounds', map);

var destination_autocomplete = new google.maps.places.Autocomplete(dropoff,options);
destination_autocomplete.bindTo('bounds', map);

var destination_autocomplete = new google.maps.places.Autocomplete(visitarea,options);
destination_autocomplete.bindTo('bounds', map);

// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.

function expandViewportToFitPlace(map, place) {
  if (place.geometry.viewport) {
    map.fitBounds(place.geometry.viewport);
  } else {
    map.setCenter(place.geometry.location);
    map.setZoom(17);
  }
}

origin_autocomplete.addListener('place_changed', function() {
  var place = origin_autocomplete.getPlace();
  if (!place.geometry) {
    window.alert("Autocomplete's returned place contains no geometry");
    return;
  }
  expandViewportToFitPlace(map, place);

  // If the place has a geometry, store its place ID and route if we have
  // the other place ID
  origin_place_id = place.place_id;
  route(origin_place_id, destination_place_id, visitarea_place_id, travel_mode,
        directionsService, directionsDisplay);
});

destination_autocomplete.addListener('place_changed', function() {
  var place = destination_autocomplete.getPlace();
  if (!place.geometry) {
    window.alert("Autocomplete's returned place contains no geometry");
    return;
  }
  expandViewportToFitPlace(map, place);

  // If the place has a geometry, store its place ID and route if we have
  // the other place ID
  destination_place_id = place.place_id;
  route(origin_place_id, destination_place_id, visitarea_place_id, travel_mode,
        directionsService, directionsDisplay);
});

visitarea_autocomplete.addListener('place_changed', function() {
  var place = visitarea_autocomplete.getPlace();
  if (!place.geometry) {
    window.alert("Autocomplete's returned place contains no geometry");
    return;
  }
  expandViewportToFitPlace(map, place);

  // If the place has a geometry, store its place ID and route if we have
  // the other place ID
  visitarea_place_id = place.place_id;
  route(origin_place_id, destination_place_id, visitarea_place_id, travel_mode,
        directionsService, directionsDisplay);
});

function route(origin_place_id, destination_place_id, visitarea_place_id, travel_mode,
               directionsService, directionsDisplay) {
  if (!origin_place_id || !destination_place_id) {
    return;
  }


  directionsService.route({
    origin: {'placeId': origin_place_id},
    destination: {'placeId': destination_place_id},
    visitarea: {'placeId': visitarea_place_id},
    optimizeWaypoints: true,
    travelMode: travel_mode
  }, function(response, status) {
    if (status === google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
      var d = response.routes[0].legs[0].distance.text;
        document.getElementById('km').value = d;


    } else {
      window.alert('Directions request failed due to ' + status);
    }
  });
}

 }

由于 web 表单中的访问区域输入字段和 javascript 函数中的所有其他相关内容,此代码无法正常工作,但如果我删除所有与访问区域相关的内容,则接送地址工作正常,并且给我所需的输出。

有什么帮助吗?

【问题讨论】:

    标签: javascript google-maps google-maps-api-3 autocomplete google-distancematrix-api


    【解决方案1】:

    我注意到一件事,dropoffvisitarea 的变量是相同的。它将用新值替换旧值,在您的情况下,该值将是 visitarea

    请检查sample 的方向和航点,演示如何使用DirectionsService 对象来获取包括航点在内的路线的方向。

    阅读documentation,了解有关在路线中使用航点的更多信息。

    这里是带有您的一些代码的示例的 sn-p:

    表格

    <div id="map"></div>
    <div id="right-panel">
    <div>
    <b>Start:</b><input id="pickup" class="controls" name="pickup" type="text"/>
    <br>
    <b>Waypoints:</b> <br>
    <input id="visitarea" class="controls" name="visitarea" type="text"/>
    <br>
    <b>End:</b>
    <input id="dropoff" class="controls" name="dropoff" type="text"/>
    <br>
      <input type="submit" id="submit">
    </div>
    <div id="directions-panel"></div>
    </div>
    

    JAVASCRIPT

    function initMap() {
        var origin_place_id = null;
        var destination_place_id = null;
        var visitarea_place_id = null;
    
        var directionsService = new google.maps.DirectionsService;
        var directionsDisplay = new google.maps.DirectionsRenderer;
        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 6,
          center: {lat: 41.85, lng: -87.65}
        });
    
        var pickup = document.getElementById('pickup');
        var dropoff = document.getElementById('dropoff');
        var visitarea = document.getElementById('visitarea');
    
        var options = {
        componentRestrictions: {country: 'pk'}//Pakistan only
        };
    
        var origin_autocomplete = new google.maps.places.Autocomplete(pickup,options);
        origin_autocomplete.bindTo('bounds', map);
    
        var destination_autocomplete = new google.maps.places.Autocomplete(dropoff,options);
        destination_autocomplete.bindTo('bounds', map);
    
        var visitarea_autocomplete = new google.maps.places.Autocomplete(visitarea,options);
        visitarea_autocomplete.bindTo('bounds', map);
    
    
        directionsDisplay.setMap(map);
    
        document.getElementById('submit').addEventListener('click', function() {
          calculateAndDisplayRoute(directionsService, directionsDisplay, origin_autocomplete, visitarea_autocomplete, destination_autocomplete);
          console.log(origin_autocomplete.getPlace().formatted_address + " "+ destination_autocomplete.getPlace().formatted_address + " "+ visitarea_autocomplete.getPlace().formatted_address);
        });
    
      }
    
      function calculateAndDisplayRoute(directionsService, directionsDisplay, start, waypoint, end) {
    
    
        var waypts = [];
            waypts.push({
              location: waypoint.getPlace().formatted_address,
              stopover: true
            });
    
    
        directionsService.route({
          origin: start.getPlace().formatted_address,
          destination: end.getPlace().formatted_address,
          waypoints: waypts,
          optimizeWaypoints: true,
          travelMode: 'DRIVING'
        }, function(response, status) {
          if (status === 'OK') {
            directionsDisplay.setDirections(response);
            var route = response.routes[0];
            var summaryPanel = document.getElementById('directions-panel');
            summaryPanel.innerHTML = '';
            // For each route, display summary information.
            for (var i = 0; i < route.legs.length; i++) {
              var routeSegment = i + 1;
              summaryPanel.innerHTML += '<b>Route Segment: ' + routeSegment +
                  '</b><br>';
              summaryPanel.innerHTML += route.legs[i].start_address + ' to ';
              summaryPanel.innerHTML += route.legs[i].end_address + '<br>';
              summaryPanel.innerHTML += route.legs[i].distance.text + '<br><br>';
            }
          } else {
            window.alert('Directions request failed due to ' + status);
          }
        });
      }
    

    【讨论】:

    • 非常好!如果您不输入航点,则会引发错误,但除此之外,一切正常。
    【解决方案2】:
    $url = 'https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=Hyderabad+Telangana+India&destinations=Mumbai+Maharashtra+India';
    $json = file_get_contents($url); // get the data from Google Maps API
    $result = json_decode($json, true); // convert it from JSON to php array
    $mi = $result['rows'][0]['elements'][0]['distance']['text'];
    $km = $mi*1.60934;
    echo round($km)." KM <br/>";
    echo $result['rows'][0]['elements'][0]['duration']['text'];
    

    【讨论】: