【问题标题】:Google Maps AutoComplete and Directions with fixed destination and variable origin具有固定目的地和可变起点的 Google 地图自动完成和路线
【发布时间】:2018-02-12 11:26:48
【问题描述】:

我正在使用带有自动完成和方向服务的 GoogleMaps 在两个标记(地点)之间绘制路线。谷歌地图文档上的示例有两个输入字段,一个用于起点,另一个用于目的地。我有目的地 LatLong。当用户选择原点时,如何使用这些 latLong 和绘制路线来修复目的地。

目的地纬度/经度:latitude: 25.116810, longitude: 55.123562

链接到 jsfiddle JsFiddle

<!DOCTYPE html>
<html>
  <head>
    <title>Place Autocomplete</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      .controls {
        margin-top: 10px;
        border: 1px solid transparent;
        border-radius: 2px 0 0 2px;
        box-sizing: border-box;
        -moz-box-sizing: border-box;
        height: 32px;
        outline: none;
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
      }

      #origin-input,
      #destination-input {
        background-color: #fff;
        font-family: Roboto;
        font-size: 15px;
        font-weight: 300;
        margin-left: 12px;
        padding: 0 11px 0 13px;
        text-overflow: ellipsis;
        width: 200px;
      }

      #origin-input:focus,
      #destination-input:focus {
        border-color: #4d90fe;
      }

      #mode-selector {
        color: #fff;
        background-color: #4d90fe;
        margin-left: 12px;
        padding: 5px 11px 0px 11px;
      }

      #mode-selector label {
        font-family: Roboto;
        font-size: 13px;
        font-weight: 300;
      }

    </style>
  </head>
  <body>
    <input id="origin-input" class="controls" type="text"
        placeholder="Enter an origin location">

    <input id="destination-input" class="controls" type="text"
        placeholder="Enter a destination location">

    <div id="mode-selector" class="controls">
      <input type="radio" name="type" id="changemode-walking" checked="checked">
      <label for="changemode-walking">Walking</label>

      <input type="radio" name="type" id="changemode-transit">
      <label for="changemode-transit">Transit</label>

      <input type="radio" name="type" id="changemode-driving">
      <label for="changemode-driving">Driving</label>
    </div>

    <div id="map"></div>

    <script>
      // This example requires the Places library. Include the libraries=places
      // parameter when you first load the API. For example:
      // <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">

      function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
          mapTypeControl: false,
          center: {lat: -33.8688, lng: 151.2195},
          zoom: 13
        });

        new AutocompleteDirectionsHandler(map);
      }

       /**
        * @constructor
       */
      function AutocompleteDirectionsHandler(map) {
        this.map = map;
        this.originPlaceId = null;
        this.destinationPlaceId = null;
        this.travelMode = 'WALKING';
        var originInput = document.getElementById('origin-input');
        var destinationInput = document.getElementById('destination-input');
        var modeSelector = document.getElementById('mode-selector');
        this.directionsService = new google.maps.DirectionsService;
        this.directionsDisplay = new google.maps.DirectionsRenderer;
        this.directionsDisplay.setMap(map);

        var originAutocomplete = new google.maps.places.Autocomplete(
            originInput, {placeIdOnly: true});
        var destinationAutocomplete = new google.maps.places.Autocomplete(
            destinationInput, {placeIdOnly: true});

        this.setupClickListener('changemode-walking', 'WALKING');
        this.setupClickListener('changemode-transit', 'TRANSIT');
        this.setupClickListener('changemode-driving', 'DRIVING');

        this.setupPlaceChangedListener(originAutocomplete, 'ORIG');
        this.setupPlaceChangedListener(destinationAutocomplete, 'DEST');

        this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(originInput);
        this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(destinationInput);
        this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(modeSelector);
      }

      // Sets a listener on a radio button to change the filter type on Places
      // Autocomplete.
      AutocompleteDirectionsHandler.prototype.setupClickListener = function(id, mode) {
        var radioButton = document.getElementById(id);
        var me = this;
        radioButton.addEventListener('click', function() {
          me.travelMode = mode;
          me.route();
        });
      };

      AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function(autocomplete, mode) {
        var me = this;
        autocomplete.bindTo('bounds', this.map);
        autocomplete.addListener('place_changed', function() {
          var place = autocomplete.getPlace();
          if (!place.place_id) {
            window.alert("Please select an option from the dropdown list.");
            return;
          }
          if (mode === 'ORIG') {
            me.originPlaceId = place.place_id;
          } else {
            me.destinationPlaceId = place.place_id;
          }
          me.route();
        });

      };

      AutocompleteDirectionsHandler.prototype.route = function() {
        if (!this.originPlaceId || !this.destinationPlaceId) {
          return;
        }
        var me = this;

        this.directionsService.route({
          origin: {'placeId': this.originPlaceId},
          destination: {'placeId': this.destinationPlaceId},
          travelMode: this.travelMode
        }, function(response, status) {
          if (status === 'OK') {
            me.directionsDisplay.setDirections(response);
          } else {
            window.alert('Directions request failed due to ' + status);
          }
        });
      };

    </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=your_api_key&libraries=places&callback=initMap"
        async defer></script>
  </body>
</html>

【问题讨论】:

    标签: google-maps google-maps-api-3 autocomplete directions


    【解决方案1】:
    1. 设置所需的目的地(硬编码)
    destination: new google.maps.LatLng(25.116810, 55.123562);
    
    1. 删除与目的地关联的自动完成

    请注意,由于某些原因,您的目的地不适用于步行路线,因此您可能需要移除 travelMode 选择。

    // This example requires the Places library. Include the libraries=places
    // parameter when you first load the API. For example:
    // <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
    
    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        mapTypeControl: false,
        center: {
          lat: 25.116810,
          lng: 55.123562
        },
        zoom: 13
      });
      var marker = new google.maps.Marker({
        map: map,
        position: new google.maps.LatLng(25.116810, 55.123562)
      });
      new AutocompleteDirectionsHandler(map);
    }
    
    /**
     * @constructor
     */
    function AutocompleteDirectionsHandler(map) {
      this.map = map;
      this.originPlaceId = null;
      this.travelMode = 'DRIVING';
      var originInput = document.getElementById('origin-input');
      this.directionsService = new google.maps.DirectionsService;
      this.directionsDisplay = new google.maps.DirectionsRenderer;
      this.directionsDisplay.setMap(map);
    
      var originAutocomplete = new google.maps.places.Autocomplete(
        originInput, {
          placeIdOnly: true
        });
    
      this.setupPlaceChangedListener(originAutocomplete, 'ORIG');
      this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(originInput);
    }
    
    // Sets a listener on a radio button to change the filter type on Places
    // Autocomplete.
    AutocompleteDirectionsHandler.prototype.setupClickListener = function(id, mode) {
      var radioButton = document.getElementById(id);
      var me = this;
      radioButton.addEventListener('click', function() {
        me.travelMode = mode;
        me.route();
      });
    };
    
    AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function(autocomplete, mode) {
      var me = this;
      autocomplete.bindTo('bounds', this.map);
      autocomplete.addListener('place_changed', function() {
        var place = autocomplete.getPlace();
        if (!place.place_id) {
          window.alert("Please select an option from the dropdown list.");
          return;
        }
        me.originPlaceId = place.place_id;
        me.route();
      });
    };
    
    AutocompleteDirectionsHandler.prototype.route = function() {
      if (!this.originPlaceId) {
        return;
      }
      var me = this;
      this.directionsService.route({
        origin: {
          'placeId': this.originPlaceId
        },
        destination: new google.maps.LatLng(25.116810, 55.123562),
        travelMode: this.travelMode
      }, function(response, status) {
        if (status === 'OK') {
          me.directionsDisplay.setDirections(response);
        } else {
          window.alert('Directions request failed due to ' + status);
        }
      });
    };
    /* Always set the map height explicitly to define the size of the div
           * element that contains the map. */
    
    #map {
      height: 100%;
    }
    
    
    /* Optional: Makes the sample page fill the window. */
    
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    .controls {
      margin-top: 10px;
      border: 1px solid transparent;
      border-radius: 2px 0 0 2px;
      box-sizing: border-box;
      -moz-box-sizing: border-box;
      height: 32px;
      outline: none;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    }
    
    #origin-input,
    #destination-input {
      background-color: #fff;
      font-family: Roboto;
      font-size: 15px;
      font-weight: 300;
      margin-left: 12px;
      padding: 0 11px 0 13px;
      text-overflow: ellipsis;
      width: 200px;
    }
    
    #origin-input:focus,
    #destination-input:focus {
      border-color: #4d90fe;
    }
    
    #mode-selector {
      color: #fff;
      background-color: #4d90fe;
      margin-left: 12px;
      padding: 5px 11px 0px 11px;
    }
    
    #mode-selector label {
      font-family: Roboto;
      font-size: 13px;
      font-weight: 300;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <title>Place Autocomplete</title>
      <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
      <meta charset="utf-8">
      <style>
    
      </style>
    </head>
    
    <body>
      <input id="origin-input" class="controls" type="text" placeholder="Enter an origin location">
    
      <div id="map"></div>
    
      <script>
      </script>
      <script src="https://maps.googleapis.com/maps/api/js?libraries=places&callback=initMap" async defer></script>
    </body>
    
    </html>

    【讨论】:

      【解决方案2】:

      this.directionsService.route({
            origin: {'placeId': this.originPlaceId},
            destination: {'placeId': this.destinationPlaceId},
            travelMode: this.travelMode
          }, function(response, status) {
      

      在带有 LatLng 的目标替换中:

      destination: {lat: 25.116810, lng: 55.123562}
      

      您可以删除目的地的输入或任何相关的事件以从用户那里获取此字段。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-16
        • 2015-02-07
        • 1970-01-01
        • 2014-03-07
        • 1970-01-01
        • 2015-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多