在源和目标之间绘制路径并连接所有点(城市)时,在谷歌地图路径中获得意外的行

时间:2015-08-07 09:02:49

标签: javascript jquery google-maps google-maps-api-3 google-places-api

  

注意:只有在输入源代码后才能点击Google地图上的查看按钮   目的地,只有在输入源和后才能添加路线点   目的地并没有留下任何路线点文本框空白(即动态文本框)

源代码摘自 geocodezip Inconsistent behaviour drawing a route between two points in Google Maps v3

// Code goes here

 var cnt = 1;
    var autocomplete = [];
    var marker = [];
    var markers = [];
    var usedIds = [];
   var map = null;
    var maxNumberOfTextboxAllowed = 5;
    var insertTextboxId = [];

  google.maps.event.addDomListener(window, 'load', function () {
        var places = new google.maps.places.Autocomplete(document.getElementById('source'));
        google.maps.event.addListener(places, 'place_changed', function () {
            var place = places.getPlace();
            var data=
                     {
                         "LocationName": document.getElementById("source").value,
                         "lat": place.geometry.location.lat().toString(),
                         "lng": place.geometry.location.lng().toString()
                     }
            if (markers.length > 0)
            {
                markers.splice(0, 1, data)
            }
            else
                markers.splice(0, 0, data);// splice(position, numberOfItemsToRemove, item)
        });
        var places1 = new google.maps.places.Autocomplete(document.getElementById('destination'));
        google.maps.event.addListener(places1, 'place_changed', function () {
            var place1 = places1.getPlace();
            var data =
                     {
                         "LocationName": document.getElementById("destination").value,
                         "lat": place1.geometry.location.lat().toString(),
                         "lng": place1.geometry.location.lng().toString()
                     }
            if (markers.length == 1) {
                markers.splice(1, 1, data);
            }
            else if(markers.length > 0)
              markers.splice(markers.length - 1, 1, data)
        });
    });





function GenerateSourceDestinationPoint() {
  if (cnt <= maxNumberOfTextboxAllowed) {
    var fieldWrapper = $("<div class='fieldwrapper' id='field" + cnt + "'/>");
    var fName = $("<input type='text' class='fieldname' id='Txtopt" + cnt + "'  name='TxtoptNm" + cnt + "'  />");
    fieldWrapper.append(fName);
    fieldWrapper.append('<br />');
    fieldWrapper.append('<br />');
    $("#abc").append(fieldWrapper);
    var newInput = [];
    var newEl = document.getElementById('Txtopt' + cnt);
    var txtboxId = 'Txtopt' + cnt;
    newInput.push(newEl);
    setupAutocomplete(autocomplete, newInput, 0, txtboxId);
    cnt = cnt + 1;
  } else
    alert("Cant create more than 5 textbox")
}

function setupAutocomplete(autocomplete, inputs, i, txtboxId) {
        insertTextboxId.push(txtboxId)
        autocomplete.push(new google.maps.places.Autocomplete(inputs[i]));
         var idx1 = autocomplete.length - 1;
        var idx = markers.length - 1;
        markers[idx + 1] = markers[idx];
        markers[idx] = {};
        google.maps.event.addListener(autocomplete[idx1], 'place_changed', function () {
            var pos = idx1 + 1;
            var place = autocomplete[idx1].getPlace();
            if (!place.geometry) {
                return;
         }
    var autoTextbox=
        {
          "LocationName": document.getElementById(insertTextboxId[idx1]).value,
                                   "lat":autocomplete[idx1].getPlace().geometry.location.lat().toString(),
 "lng": autocomplete[idx1].getPlace().geometry.location.lng().toString()
        }
            markers[idx] = autoTextbox;
            initialize();
        });
    }

   function initialize() {
        var bounds = new google.maps.LatLngBounds();
        var mapOptions = {
            center: new google.maps.LatLng(parseFloat(markers[0].lat), parseFloat(markers[0].lng)),
            zoom: 10,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var path = new google.maps.MVCArray();
        var service = new google.maps.DirectionsService();

        var infoWindow = new google.maps.InfoWindow();
        map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
        var poly = new google.maps.Polyline({
            map: map,
            strokeColor: '#F3443C'
        });
        var lat_lng = new Array();
        var marker = new google.maps.Marker({
        position: map.getCenter(),
            map: map
        });
        bounds.extend(marker.getPosition());
        for (var i = 0; i < markers.length; i++) {
            if ((i + 1) < markers.length) {
                var src = new google.maps.LatLng(parseFloat(markers[i].lat),
                                                 parseFloat(markers[i].lng));
                var smarker = new google.maps.Marker({ position: src, map: map });
                bounds.extend(smarker.getPosition());
                var des = new google.maps.LatLng(parseFloat(markers[i + 1].lat),
                                                 parseFloat(markers[i + 1].lng));
                var dmarker = new google.maps.Marker({ position: des, map: map });
                bounds.extend(dmarker.getPosition());
                service.route({
                    origin: src,
                    destination: des,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                }, function (result, status) {
                    if (status == google.maps.DirectionsStatus.OK) {
                        for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
                            path.push(result.routes[0].overview_path[i]);
                        }
                        poly.setPath(path);
                        map.fitBounds(bounds);
                    }
                });
            }
        }
    }
  html, body, #map_canvas {
        height: 100% !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    #panel {
        position: absolute;
        top: 5px;
        left: 50%;
        margin-left: -180px;
        z-index: 5;
        background-color: #fff;
        padding: 5px;
        border: 1px solid #999;
    }

    /*
        Provide the following styles for both ID and class,
        where ID represents an actual existing "panel" with
        JS bound to its name, and the class is just non-map
        content that may already have a different ID with
        JS bound to its name.
        */

    #panel, .panel {
        font-family: 'Roboto','sans-serif';
        line-height: 30px;
        padding-left: 10px;
    }

        #panel select, #panel input, .panel select, .panel input {
            font-size: 15px;
        }

        #panel select, .panel select {
            width: 100%;
        }

        #panel i, .panel i {
            font-size: 12px;
        }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places,geometry"></script>
<input type="button" onclick="initialize()" value="View on Google Map" />

    <br /><br />
    <label>Source</label>
    <input type="text" value="" name="source" id="source">
    <br /><br />
    <label>Destination</label>
    <input type="text" value="" name="destination" id="destination">
    <br /><br />
    <button onclick="GenerateSourceDestinationPoint()" class="btn btn-primary" type="button" >Add Points</button>
    <div style="border: 1px solid -moz-nativehyperlinktext;"></div>
    <div id="abc">
    </div>

    <br /><br />
    <div style="height:400px;width:1000px">
        <div id="map_canvas"></div>
    </div>

我想在我的来源和目的地之间绘制路径,并连接所有我的点(即城市)落在源和目的地之间

例如:如果我的来源是斯旺西,英国,目的地伦敦,英国,我的路线点如下:

1 )添加第一个路径加的夫,英国。获得如下所示的完美输出: enter image description here

2 )添加第二路径英国纽波特。获得如下所示的完美输出:enter image description here

3 )添加第三个路径巴斯,英国。获得如下所示的完美输出:enter image description here

4 )当我将第二路线点英国纽波特更改为英国布里斯托尔时,现在出现了问题然后我在谷歌地图中得到意想不到的行,如下所示:enter image description here

5 预期输出enter image description here

2 个答案:

答案 0 :(得分:2)

问题:地理编码以异步方式运行。无法保证路由回调将按所需顺序执行。

当您获得这些直线时,订单将混淆(也发生在原始演示中),因为您始终将overview_polyline附加到路径。

您必须先创建整个路径(按正确顺序),然​​后绘制折线。

然而:

  1. 创建一个新的Map(这会影响map-loads-quota)不是一个好方法。
  2. 当您将航点限制为5时,您可以使用DirectionsService来请求完整航线(最多可以有8个航路点)

答案 1 :(得分:1)

如果您需要航路点,请将其包含在路线服务请求中。你的问题是将路线的各个部分放在一起。

function initialize() {
    var bounds = new google.maps.LatLngBounds();
    var mapOptions = {
        center: new google.maps.LatLng(parseFloat(markers[0].lat), parseFloat(markers[0].lng)),
        zoom: 10,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var path = new google.maps.MVCArray();
    var service = new google.maps.DirectionsService();

    var infoWindow = new google.maps.InfoWindow();
    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
    var poly = new google.maps.Polyline({
        map: map,
        strokeColor: '#F3443C'
    });
    var lat_lng = [];
    var marker = new google.maps.Marker({
    position: map.getCenter(),
        map: map
    });
    bounds.extend(marker.getPosition()); 
   var src,des;
   var waypoints = [];

    for (var i = 0; i < markers.length; i++) {
        if (i===0) {
            src = new google.maps.LatLng(parseFloat(markers[i].lat),
                                             parseFloat(markers[i].lng));
            var smarker = new google.maps.Marker({ position: src, map: map });
            bounds.extend(smarker.getPosition());
        } else if (i==markers.length-1) {
            des = new google.maps.LatLng(parseFloat(markers[i].lat),
                                             parseFloat(markers[i].lng));
            var dmarker = new google.maps.Marker({ position: des, map: map });
            bounds.extend(dmarker.getPosition());
        } else {
            var latlng = new google.maps.LatLng(markers[i].lat, markers[i].lng);
            waypoints.push({location: latlng,
                            stopover:true});
            var marker = new google.maps.Marker({
                position: latlng,
                map: map
            });
        }
    }
            service.route({
                origin: src,
                destination: des,
                waypoints: waypoints,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            }, function (result, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
                        path.push(result.routes[0].overview_path[i]);
                    }
                    poly.setPath(path);
                    map.fitBounds(bounds);
                }
            });
        }

proof of concept fiddle

代码段

var cnt = 1;
var autocomplete = [];
var marker = [];
var markers = [];
var usedIds = [];
var map = null;
var maxNumberOfTextboxAllowed = 5;
var insertTextboxId = [];

google.maps.event.addDomListener(window, 'load', function() {
  var places = new google.maps.places.Autocomplete(document.getElementById('source'));
  google.maps.event.addListener(places, 'place_changed', function() {
    var place = places.getPlace();
    var data = {
      "LocationName": document.getElementById("source").value,
      "lat": place.geometry.location.lat().toString(),
      "lng": place.geometry.location.lng().toString()
    };
    if (markers.length > 0) {
      markers.splice(0, 1, data);
    } else
      markers.splice(0, 0, data); // splice(position, numberOfItemsToRemove, item)
  });
  var places1 = new google.maps.places.Autocomplete(document.getElementById('destination'));
  google.maps.event.addListener(places1, 'place_changed', function() {
    var place1 = places1.getPlace();
    var data = {
      "LocationName": document.getElementById("destination").value,
      "lat": place1.geometry.location.lat().toString(),
      "lng": place1.geometry.location.lng().toString()
    }
    if (markers.length == 1) {
      markers.splice(1, 1, data);
    } else if (markers.length > 0)
      markers.splice(markers.length - 1, 1, data)
  });
});





function GenerateSourceDestinationPoint() {
  if (cnt <= maxNumberOfTextboxAllowed) {
    var fieldWrapper = $("<div class='fieldwrapper' id='field" + cnt + "'/>");
    var valueStr;
    if (cnt == 1) {
      valueStr = "Cardiff, UK";
    } else if (cnt == 2) {
      valueStr = "Newport, UK";
    } else if (cnt == 3) {
      valueStr = "Bath, UK";
    } else {
      valueStr = "";
    }
    var fName = $("<input type='text' class='fieldname' id='Txtopt" + cnt + "'  name='TxtoptNm" + cnt + "' value='" + valueStr + "' />");
    fieldWrapper.append(fName);
    fieldWrapper.append('<br />');
    fieldWrapper.append('<br />');
    $("#abc").append(fieldWrapper);
    var newInput = [];
    var newEl = document.getElementById('Txtopt' + cnt);
    var txtboxId = 'Txtopt' + cnt;
    newInput.push(newEl);
    setupAutocomplete(autocomplete, newInput, 0, txtboxId);
    cnt = cnt + 1;
  } else
    alert("Cant create more than 5 textbox");
}

function setupAutocomplete(autocomplete, inputs, i, txtboxId) {
  insertTextboxId.push(txtboxId);
  autocomplete.push(new google.maps.places.Autocomplete(inputs[i]));
  var idx1 = autocomplete.length - 1;
  var idx = markers.length - 1;
  markers[idx + 1] = markers[idx];
  markers[idx] = {};
  google.maps.event.addListener(autocomplete[idx1], 'place_changed', function() {
    var pos = idx1 + 1;
    var place = autocomplete[idx1].getPlace();
    if (!place.geometry) {
      return;
    }
    var autoTextbox = {
      "LocationName": document.getElementById(insertTextboxId[idx1]).value,
      "lat": autocomplete[idx1].getPlace().geometry.location.lat().toString(),
      "lng": autocomplete[idx1].getPlace().geometry.location.lng().toString()
    }
    markers[idx] = autoTextbox;
    initialize();
  });
}

function initialize() {
  var bounds = new google.maps.LatLngBounds();
  var mapOptions = {
    center: new google.maps.LatLng(parseFloat(markers[0].lat), parseFloat(markers[0].lng)),
    zoom: 10,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  var path = new google.maps.MVCArray();
  var service = new google.maps.DirectionsService();

  var infoWindow = new google.maps.InfoWindow();
  map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
  var poly = new google.maps.Polyline({
    map: map,
    strokeColor: '#F3443C'
  });
  var lat_lng = [];
  var marker = new google.maps.Marker({
    position: map.getCenter(),
    map: map
  });
  bounds.extend(marker.getPosition());
  var src, des;
  var waypoints = [];

  for (var i = 0; i < markers.length; i++) {
    if (i === 0) {
      src = new google.maps.LatLng(parseFloat(markers[i].lat),
        parseFloat(markers[i].lng));
      var smarker = new google.maps.Marker({
        position: src,
        map: map
      });
      bounds.extend(smarker.getPosition());
    } else if (i == markers.length - 1) {
      des = new google.maps.LatLng(parseFloat(markers[i].lat),
        parseFloat(markers[i].lng));
      var dmarker = new google.maps.Marker({
        position: des,
        map: map
      });
      bounds.extend(dmarker.getPosition());
    } else {
      var latlng = new google.maps.LatLng(markers[i].lat, markers[i].lng);
      waypoints.push({
        location: latlng,
        stopover: true
      });
      var marker = new google.maps.Marker({
        position: latlng,
        map: map
      });
    }
  }
  service.route({
    origin: src,
    destination: des,
    waypoints: waypoints,
    travelMode: google.maps.DirectionsTravelMode.DRIVING
  }, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
        path.push(result.routes[0].overview_path[i]);
      }
      poly.setPath(path);
      map.fitBounds(bounds);
    }
  });
}
html,
body,
#map_canvas {
  height: 100% !important;
  margin: 0 !important;
  padding: 0 !important;
}
#panel {
  position: absolute;
  top: 5px;
  left: 50%;
  margin-left: -180px;
  z-index: 5;
  background-color: #fff;
  padding: 5px;
  border: 1px solid #999;
}
/*
        Provide the following styles for both ID and class,
        where ID represents an actual existing "panel" with
        JS bound to its name, and the class is just non-map
        content that may already have a different ID with
        JS bound to its name.
        */

#panel,
.panel {
  font-family: 'Roboto', 'sans-serif';
  line-height: 30px;
  padding-left: 10px;
}
#panel select,
#panel input,
.panel select,
.panel input {
  font-size: 15px;
}
#panel select,
.panel select {
  width: 100%;
}
#panel i,
.panel i {
  font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry,places&ext=.js"></script>
<input type="button" onclick="initialize()" value="View on Google Map" />

<br />
<br />
<label>Source</label>
<input type="text" value="Swansea, UK" name="source" id="source">
<br />
<br />
<label>Destination</label>
<input type="text" value="London, UK" name="destination" id="destination">
<br />
<br />
<button onclick="GenerateSourceDestinationPoint()" class="btn btn-primary" type="button">Add Points</button>
<div style="border: 1px solid -moz-nativehyperlinktext;"></div>
<div id="abc">
</div>

<br />
<br />
<div style="height:400px;width:600px">
  <div id="map_canvas"></div>
</div>