Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've been researching this all day and still haven't come across a solution that works. I'm using the Google Maps Distance Matrix Service with 1 origin and 14 destinations. I modified the sample code from Google (https://developers.google.com/maps/documentation/javascript/examples/distance-matrix) and just added more destinations to test it out. With anything over 10 destinations, the OVER_QUERY_LIMIT error occurs and mis-places a marker.
From the usage limits I found (100 elements per 10 seconds), I shouldn't be hitting the limit at all. I have also tried inserting my API Key in this line, to no avail:
src="https://maps.googleapis.com/maps/api/js?v=3.exp"
Any help would be appreciated! Thanks.
Code changes to the sample code from Google:
var destinationA = new google.maps.LatLng(45.465422,9.185924);
var destinationB = new google.maps.LatLng(41.385064,2.173403);
var destinationC = new google.maps.LatLng(40.416775,-3.70379);
var destinationD = new google.maps.LatLng(51.507351,-0.127758);
var destinationE = new google.maps.LatLng(48.856614,2.352222);
var destinationF = new google.maps.LatLng(41.902784,12.496366);
var destinationG = new google.maps.LatLng(50.85034,4.35171);
var destinationH = new google.maps.LatLng(46.198392,6.142296);
var destinationI = new google.maps.LatLng(47.36865,8.539183);
var destinationJ = new google.maps.LatLng(53.408371,-2.991573);
var destinationK = new google.maps.LatLng(37.389092,-5.984459);
var destinationL = new google.maps.LatLng(53.349805,-6.26031);
var destinationM = new google.maps.LatLng(55.864237,-4.251806);
var destinationN = new google.maps.LatLng(51.92442,4.477733);
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: [destinationA, destinationB,destinationC, destinationD,destinationE, destinationF,destinationG, destinationH,destinationI, destinationJ,destinationK, destinationL, destinationM, destinationN],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
}
The OVER_QUERY_ERROR is coming from the geocoder, not the DistanceMatrix call. Remove this line:
addMarker(destinations[j], true);
(you don't need the geocoder, you already have the coordinates for the markers)
working code snippet:
var map;
var geocoder;
var bounds = new google.maps.LatLngBounds();
var markersArray = [];
var origin = new google.maps.LatLng(55.930, -3.118);
var origin2 = 'Greenwich, England';
var destinationA = new google.maps.LatLng(45.465422, 9.185924);
var destinationB = new google.maps.LatLng(41.385064, 2.173403);
var destinationC = new google.maps.LatLng(40.416775, -3.70379);
var destinationD = new google.maps.LatLng(51.507351, -0.127758);
var destinationE = new google.maps.LatLng(48.856614, 2.352222);
var destinationF = new google.maps.LatLng(41.902784, 12.496366);
var destinationG = new google.maps.LatLng(50.85034, 4.35171);
var destinationH = new google.maps.LatLng(46.198392, 6.142296);
var destinationI = new google.maps.LatLng(47.36865, 8.539183);
var destinationJ = new google.maps.LatLng(53.408371, -2.991573);
var destinationK = new google.maps.LatLng(37.389092, -5.984459);
var destinationL = new google.maps.LatLng(53.349805, -6.26031);
var destinationM = new google.maps.LatLng(55.864237, -4.251806);
var destinationN = new google.maps.LatLng(51.92442, 4.477733);
var destinationIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=D|FF0000|000000';
var originIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=O|FFFF00|000000';
function initialize() {
var opts = {
center: new google.maps.LatLng(55.53, 9.4),
zoom: 10
};
map = new google.maps.Map(document.getElementById('map-canvas'), opts);
geocoder = new google.maps.Geocoder();
}
function calculateDistances() {
deleteOverlays();
var destinations = [destinationA, destinationB, destinationC, destinationD, destinationE, destinationF, destinationG, destinationH, destinationI, destinationJ, destinationK, destinationL, destinationM, destinationN];
for (var i = 0; i < destinations.length; i++) {
bounds.extend(destinations[i]);
var marker = new google.maps.Marker({
map: map,
position: destinations[i],
icon: destinationIcon
});
markersArray.push(marker);
}
map.fitBounds(bounds);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [origin],
destinations: destinations,
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var outputDiv = document.getElementById('outputDiv');
outputDiv.innerHTML = '';
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
addMarker(origins[i], false);
for (var j = 0; j < results.length; j++) {
// addMarker(destinations[j], true);
outputDiv.innerHTML += "<b>"+j+":</b>"+origins[i] + ' to ' + destinations[j] + ': ' + results[j].distance.text + ' in ' + results[j].duration.text + '<br>';
}
}
}
}
function addMarker(location, isDestination) {
var icon;
if (isDestination) {
icon = destinationIcon;
} else {
icon = originIcon;
}
geocoder.geocode({
'address': location
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
bounds.extend(results[0].geometry.location);
map.fitBounds(bounds);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
icon: icon
});
markersArray.push(marker);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
function deleteOverlays() {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
markersArray = [];
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 100%;
width: 50%;
}
#content-pane {
float: right;
width: 48%;
padding-left: 2%;
}
#outputDiv {
font-size: 11px;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<p>
<button type="button" onclick="calculateDistances();">Calculate distances</button>
</p>
</div>
<div id="outputDiv"></div>
</div>
<div id="map-canvas"></div>
Related
I'm trying to make origin SearchBox destination be string with legit direction, but when I do so I still need to select the first option for it to work (to calculate distance).
Got the this searching around to calculate distance between 2 points and it works perfectly:
How can I add multiple searchBoxes in my google maps api web?
I got a string for example :albrook mall which i know exist( this string is dynamic is coming from a variable and all address are validated. get the needed address pass it to a variable so I can read it on the frontEnd, and set the value of search box in the html. the value is updated with jquery
But what happens is that I still have to click on the origin search box then this list all possible locations which in my case is the first one, how can I make the map either auto select the first option or recognize the address that is set in the input value?
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {
lat: 9.0271554,
lng: 79.4816371
},
zoom: 15
});
var marker = new google.maps.Marker({
map: map,
draggable: false
});
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(initialLocation);
/*marker.setPosition(initialLocation); */
});
}
new AutocompleteDirectionsHandler(map);
}
/**
* #constructor
*/
function AutocompleteDirectionsHandler(map) {
this.map = map;
this.originPlaceId = null;
this.destinationPlaceId = null;
this.travelMode = 'DRIVING';
this.avoidTolls = true;
this.avoidHighways= true;
//this.provideRouteAlternatives= true,
this.avoidFerries= true;
this.directionsService = new google.maps.DirectionsService();
this.directionsRenderer = new google.maps.DirectionsRenderer();
this.directionsRenderer.setMap(map);
var originInput = document.getElementById('orign');
var destinationInput = document.getElementById('destn');
var originAutocomplete = new google.maps.places.SearchBox(originInput);
var destinationAutocomplete =
new google.maps.places.SearchBox(destinationInput);
this.setupPlaceChangedListener(originAutocomplete, 'ORIG');
this.setupPlaceChangedListener(destinationAutocomplete, 'DEST');
}
AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function(
autocomplete, mode) {
var me = this;
autocomplete.bindTo('bounds', this.map);
autocomplete.addListener('places_changed', function() {
var places = autocomplete.getPlaces();
var place = places[0];
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,
avoidTolls: this.avoidTolls
},
function(response, status) {
if (status === 'OK') {
me.directionsRenderer.setDirections(response);
computeTotalDistance(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
};
// from Google Maps API: Total distance with waypoints
// https://stackoverflow.com/questions/12802202/google-maps-api-total-distance-with-waypoints
function computeTotalDistance(result) {
var totalDist = 0;
var totalTime = 0;
var myroute = result.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
totalDist += myroute.legs[i].distance.value;
totalTime += myroute.legs[i].duration.value;
}
totalDist = totalDist / 1000.
time = (totalTime / 60).toFixed(2)
document.getElementById("totalkm").innerHTML ="" + totalDist + "km" ;
document.getElementById("totaltime").innerHTML ="" + time + " minutos";
if(totalDist <= 5){
document.getElementById("totalCost").innerHTML =" $3.50";
}
else{
kmPrice = (totalDist - 5) * 0.75;
document.getElementById("totalCost").innerHTML ="$" +(kmPrice + 3.50).toFixed(2)+ "";
}
}
function send_handle(){
let name=document.getElementById("name").value;
///let lastname= document.getElementById("lastname").value;
let inst= document.getElementById("instructions").value;
let origin= document.querySelector(".selectButtons input#orign").value;
let destination= document.querySelector(".selectButtons input#destn").value;
let cost= document.getElementById("totalCost").innerHTML;
let distance= document.getElementById("totalkm").innerHTML;
// win.focus();
}
</script>
<html>
<div class="selectButtons" >
<input type="text" id="orign" placeholder="origen">
<input type="text" id="destn" placeholder="destino">
<span> Distancia en KM <div id="totalkm">0km</div> </span>
<span> Distancia en tiempo <div id="totaltime">o.oo</div> </span>
<span> costo por envio<div id="totalCost">$0</div></div> </span>
</div>
</html>
You can call the places service to get the PlaceId (with your string), then pass that placeId into the constructor for your AutocompleteDirectionsHandler or if you already have the PlaceId (you are allowed to store those), just use it, although you probably want to initialize the origin input with the string.
var origin = "Allbrook, Panama";
var originInput = document.getElementById('orign');
originInput.value = origin;
const request = {
query: origin,
fields: ["name", "geometry", "place_id"],
};
var originPlaceId;
var service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery(request, (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK && results) {
originPlaceId = results[0].place_id;
console.log("placeId="+originPlaceId+" coords="+results[0].geometry.location.toUrlValue(6));
new AutocompleteDirectionsHandler(map, originPlaceId);
map.setCenter(results[0].geometry.location);
}
});
Add the initial origin placeId to the AutocompleteDirectionsHandler constructor:
function AutocompleteDirectionsHandler(map, originPlaceId) {
this.map = map;
this.originPlaceId = originPlaceId;
// ...
on load:
after selecting destination from dropdown:
code snippet:
let map;
function initMap() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {
lat: 9.0271554,
lng: 79.4816371
},
zoom: 15
});
var origin = "Allbrook, Panama";
var originInput = document.getElementById('orign');
originInput.value = origin;
const request = {
query: origin,
fields: ["name", "geometry", "place_id"],
};
var originPlaceId;
var service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery(request, (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK && results) {
originPlaceId = results[0].place_id;
console.log("placeId="+originPlaceId+" coords="+results[0].geometry.location.toUrlValue(6));
new AutocompleteDirectionsHandler(map, originPlaceId);
map.setCenter(results[0].geometry.location);
}
});
var marker = new google.maps.Marker({
map: map,
draggable: false
});
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(initialLocation);
/*marker.setPosition(initialLocation); */
});
}
}
/**
* #constructor
*/
function AutocompleteDirectionsHandler(map, originPlaceId) {
this.map = map;
this.originPlaceId = originPlaceId;
this.destinationPlaceId = null;
this.travelMode = 'DRIVING';
this.avoidTolls = true;
this.avoidHighways = true;
//this.provideRouteAlternatives= true,
this.avoidFerries = true;
this.directionsService = new google.maps.DirectionsService();
this.directionsRenderer = new google.maps.DirectionsRenderer();
this.directionsRenderer.setMap(map);
var originInput = document.getElementById('orign');
var destinationInput = document.getElementById('destn');
var originAutocomplete = new google.maps.places.SearchBox(originInput);
var destinationAutocomplete =
new google.maps.places.SearchBox(destinationInput);
this.setupPlaceChangedListener(originAutocomplete, 'ORIG');
this.setupPlaceChangedListener(destinationAutocomplete, 'DEST');
}
AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function(
autocomplete, mode) {
var me = this;
autocomplete.bindTo('bounds', this.map);
autocomplete.addListener('places_changed', function() {
var places = autocomplete.getPlaces();
var place = places[0];
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,
avoidTolls: this.avoidTolls
},
function(response, status) {
if (status === 'OK') {
me.directionsRenderer.setDirections(response);
computeTotalDistance(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
};
// from Google Maps API: Total distance with waypoints
// https://stackoverflow.com/questions/12802202/google-maps-api-total-distance-with-waypoints
function computeTotalDistance(result) {
var totalDist = 0;
var totalTime = 0;
var myroute = result.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
totalDist += myroute.legs[i].distance.value;
totalTime += myroute.legs[i].duration.value;
}
totalDist = totalDist / 1000.
time = (totalTime / 60).toFixed(2)
document.getElementById("totalkm").innerHTML = "" + totalDist + "km";
document.getElementById("totaltime").innerHTML = "" + time + " minutos";
if (totalDist <= 5) {
document.getElementById("totalCost").innerHTML = " $3.50";
} else {
kmPrice = (totalDist - 5) * 0.75;
document.getElementById("totalCost").innerHTML = "$" + (kmPrice + 3.50).toFixed(2) + "";
}
}
function send_handle() {
let name = document.getElementById("name").value;
///let lastname= document.getElementById("lastname").value;
let inst = document.getElementById("instructions").value;
let origin = document.querySelector(".selectButtons input#orign").value;
let destination = document.querySelector(".selectButtons input#destn").value;
let cost = document.getElementById("totalCost").innerHTML;
let distance = document.getElementById("totalkm").innerHTML;
// win.focus();
}
function createMarker(place) {
if (!place.geometry || !place.geometry.location) return;
const marker = new google.maps.Marker({
map,
position: place.geometry.location,
});
google.maps.event.addListener(marker, "click", () => {
infowindow.setContent(place.name || "");
infowindow.open(map);
});
}
window.initMap = initMap;
#map-canvas {
height: 80%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<html>
<div class="selectButtons">
<input type="text" id="orign" placeholder="origen" />
<input type="text" id="destn" placeholder="destino" />
<span> Distancia en KM <div id="totalkm">0km</div> </span>
<span> Distancia en tiempo <div id="totaltime">o.oo</div> </span>
<span> costo por envio<div id="totalCost">$0</div> </span>
</div>
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&callback=initMap" async defer></script>
</html>
I'm trying to make a origin and destination menu, so the user will choose the locations in each input, and each input will add a marker to the map and then it will calculate the distance, this is my progress so far: I've successfully added a map with a search box, but I can't create another one and I don't know how to do this.
This is my code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=places"></script>
<div style="background-color: #FFC012">
<input type="text" id="orign" placeholder="origin">
<input type="text" id="destn" placeholder="destination">
<br>
<div id="map-canvas">
<script>
var map = new google.maps.Map(document.getElementById('map-canvas'),{
center:{
lat: 19.4978,
lng: -99.1269
},
zoom:15
});
var marker = new google.maps.Marker({
map:map,
draggable: false
});
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(initialLocation);
/*marker.setPosition(initialLocation); */
});
}
var searchBox = new google.maps.places.SearchBox(document.getElementById('orign'));
google.maps.event.addListener(searchBox, 'places_changed',function(){
var places = searchBox.getPlaces();
var bounds = new google.maps.LatLngBounds();
var i, place;
for(i=0; place=places[i];i++){
bounds.extend(place.geometry.location);
marker.setPosition(place.geometry.location);
}
map.fitBounds(bounds);
map.setZoom(15);
})
</script>
</div>
</div>
One option would be to start from the Autocomplete Directions Example in the documentation, change the Autocomplete objects to SearchBox objects, and the associated code to account for the differences (SearchBox has a places_changed event, Autocomplete has place_changed (singular); the routine to get the results also has a different name (singular vs. plural).
/**
* #constructor
*/
function AutocompleteDirectionsHandler(map) {
this.map = map;
this.originPlaceId = null;
this.destinationPlaceId = null;
this.travelMode = 'DRIVING';
this.directionsService = new google.maps.DirectionsService();
this.directionsRenderer = new google.maps.DirectionsRenderer();
this.directionsRenderer.setMap(map);
var originInput = document.getElementById('orign');
var destinationInput = document.getElementById('destn');
var originAutocomplete = new google.maps.places.SearchBox(originInput);
var destinationAutocomplete =
new google.maps.places.SearchBox(destinationInput);
this.setupPlaceChangedListener(originAutocomplete, 'ORIG');
this.setupPlaceChangedListener(destinationAutocomplete, 'DEST');
}
AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function(
autocomplete, mode) {
var me = this;
autocomplete.bindTo('bounds', this.map);
autocomplete.addListener('places_changed', function() {
var places = autocomplete.getPlaces();
var place = places[0];
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();
});
};
Add a function to calculate the length of the returned route (from the question: Google Maps API: Total distance with waypoints):
function computeTotalDistance(result) {
var totalDist = 0;
var totalTime = 0;
var myroute = result.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
totalDist += myroute.legs[i].distance.value;
totalTime += myroute.legs[i].duration.value;
}
totalDist = totalDist / 1000.
document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes";
}
proof of concept fiddle
code snippet:
// 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-canvas'), {
center: {
lat: 19.4978,
lng: -99.1269
},
zoom: 15
});
var marker = new google.maps.Marker({
map: map,
draggable: false
});
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(initialLocation);
/*marker.setPosition(initialLocation); */
});
}
new AutocompleteDirectionsHandler(map);
}
/**
* #constructor
*/
function AutocompleteDirectionsHandler(map) {
this.map = map;
this.originPlaceId = null;
this.destinationPlaceId = null;
this.travelMode = 'DRIVING';
this.directionsService = new google.maps.DirectionsService();
this.directionsRenderer = new google.maps.DirectionsRenderer();
this.directionsRenderer.setMap(map);
var originInput = document.getElementById('orign');
var destinationInput = document.getElementById('destn');
var originAutocomplete = new google.maps.places.SearchBox(originInput);
var destinationAutocomplete =
new google.maps.places.SearchBox(destinationInput);
this.setupPlaceChangedListener(originAutocomplete, 'ORIG');
this.setupPlaceChangedListener(destinationAutocomplete, 'DEST');
}
AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function(
autocomplete, mode) {
var me = this;
autocomplete.bindTo('bounds', this.map);
autocomplete.addListener('places_changed', function() {
var places = autocomplete.getPlaces();
var place = places[0];
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.directionsRenderer.setDirections(response);
computeTotalDistance(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
};
// from Google Maps API: Total distance with waypoints
// https://stackoverflow.com/questions/12802202/google-maps-api-total-distance-with-waypoints
function computeTotalDistance(result) {
var totalDist = 0;
var totalTime = 0;
var myroute = result.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
totalDist += myroute.legs[i].distance.value;
totalTime += myroute.legs[i].duration.value;
}
totalDist = totalDist / 1000.
document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes";
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map-canvas {
height: 80%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div style="background-color: #FFC012; height:100%; width:100%;">
<input type="text" id="orign" placeholder="origin" value="Lindavista Vallejo III Secc">
<input type="text" id="destn" placeholder="destination" value="Lienzo Charro de La Villa">
<div id="total"></div>
<br>
<div id="map-canvas"></div>
</div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&callback=initMap" async defer></script>
I am a newbie ith google maps distance matrix. But I need it to calculate most effecient route between several locations.
However using a jsfiddle example I can even make it create a route with locations in my region:
My Js fiddle
Example js Fiddle tha I used as base
Basically changed destinations to:
var origin = "Aeroporto da Madeira"
var destinations = [
"Hotel Four Views Baía, Rua das Maravilhas, Funchal",
"R. José Joaquim da Costa 112, 9325-031 Estreito De Câmara, Portugal",
"Q.ta de São João, 2735-521, Portugal"];
These places exist and if I search at google maps appear.
This maybe a very stupid question but what am I doing wrong?
The fact that an address may be geocoded must not mean that a route may be calculated to another location.
In your case the origin is on madeira(an island), but the last destination isn't placed on madeira(a driving route may not be calculated....obviously there are no ferries available...., your function stops running because of the attempt to access a undefined variable routes.elements[i].duration.value)
check the status of the element before you access it's properties
var map;
var geocoder;
var origin = "Aeroporto da Madeira"
var destinations = [
"Hotel Four Views Baía, Rua das Maravilhas, Funchal",
"R. José Joaquim da Costa 112, 9325-031 Estreito De Câmara, Portugal",
"Q.ta de São João, 2735-521, Portugal"
];
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [origin], //array of origins
destinations: destinations, //array of destinations
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
//we only have one origin so there should only be one row
var routes = response.rows[0];
//need to find the shortest
var lowest = Number.POSITIVE_INFINITY;
var tmp;
var shortestRouteIdx = -1;
var resultText = "Possible Routes: <br/>";
for (var i = routes.elements.length - 1; i >= 0; i--) {
//do we got a result for the element?
if (routes.elements[i].status === google.maps.DistanceMatrixElementStatus.OK) {
tmp = routes.elements[i].duration.value;
resultText += "Route " + destinations[i] + ": " + tmp + "<br/>";
if (tmp < lowest) {
lowest = tmp;
shortestRouteIdx = i;
}
}
}
//log the routes and duration.
document.getElementById('results').innerHTML = resultText;
if (shortestRouteIdx > -1) {
//get the shortest route
var shortestRoute = destinations[shortestRouteIdx];
//now we need to map the route.
calculateRoute(origin, shortestRoute)
} else {
alert('no route available');
}
}
}
//Calculate the route of the shortest distance we found.
function calculateRoute(start, end) {
var request = {
origin: start,
destination: end,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
}
});
}
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var centerPosition = new google.maps.LatLng(32.670159, -16.978268);
var options = {
zoom: 12,
center: centerPosition,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), options);
directionsDisplay.setMap(map);
calculateDistances();
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#results {
position: fixed;
top: 0;
right: 0;
background: gold;
}
<div id="map"></div>
<div id="results"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3"></script>
I've got a web app that needs 'distance from me' information for properties displayed on a map.
I'm using googles Distance Matrix Service
distanceService = new google.maps.DistanceMatrixService();
I'm calling the service with one origin and multiple destinations.
var params = {
origins: [currentLocation],
destinations: endPoints,
travelMode: google.maps.TravelMode.DRIVING
}
distanceService.getDistanceMatrix(params, saveDistances);
My endPoints are an array of google.maps.LatLng objects taken from my properties. However when the results are returned they've changed these to addresses, and there's no longer any reference to the LatLng's.
Does anyone know if the Distance Matrix Service guarantees to return results in the same order I sent them? I couldn't see anything in the docs. I really don't want to start calling the geocoding services just to match back to my properties (especially as the LatLng's return won't be an exact match)
They are returned in the same order they are sent.
That isn't specifically stated, but the way I read the documentation it is implied.
quick test fiddle
code snippet:
var service = new google.maps.DistanceMatrixService();
var places = [{
address: "New York, NY",
lat: 40.7143528,
lng: -74.0059731
}, {
address: "Tampa, FL",
lat: 27.950575,
lng: -82.4571776
}, {
address: "Newark, NJ",
lat: 40.735657,
lng: -74.1723667
}, {
address: "Boston, MA",
lat: 42.3584308,
lng: -71.0597732
}, {
address: "Baltimore, MD",
lat: 39.2903848,
lng: -76.6121893
}];
var foundlatlng = new google.maps.LatLng(40.65, -73.95); // Brooklyn, NY
var gotoLoc = [];
for (var i = 0; i < places.length; i++) {
gotoLoc.push(new google.maps.LatLng(places[i].lat, places[i].lng));
}
var service = new google.maps.DistanceMatrixService(); //request distance matrix
var outputdiv = document.getElementById('info');
// var goto = new google.maps.LatLng(places[i].lat, places[i].lng);
function callback(response, status) {
var distancefield = distancefield;
if (status == google.maps.DistanceMatrixStatus.OK) {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var htmlString = "<table border='1'>";
var bounds = new google.maps.LatLngBounds();
for (var c = 0; c < response.rows.length; c++) {
var results = response.rows[c].elements;
for (var r = 0; r < results.length; r++) {
var element = results[r];
var distancetext = element.distance.text;
var durationtext = element.duration.text;
var to = destinations[r];
htmlString += "<tr><td>" + (r + 1) + "</td><td>" + places[r].address + "</td><td>" + response.originAddresses[c] + "</td><td>" + to + "</td><td>" + distancetext + "</td><td>" + durationtext + "</td></tr>";
var marker = new google.maps.Marker({
icon: 'http://gmaps-samples.googlecode.com/svn/trunk/markers/blue/marker' + (r + 1) + '.png',
position: {
lat: places[r].lat,
lng: places[r].lng
},
map: map
});
bounds.extend(marker.getPosition());
} //end for r
} // end for c
map.fitBounds(bounds);
htmlString += "</table>";
document.getElementById('info').innerHTML = htmlString;
} //end if status=ok
} //end callback
// console.log(places);
var map;
var geocoder = new google.maps.Geocoder();
function initialize() {
var mapOptions = {
zoom: 8,
center: foundlatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
service.getDistanceMatrix({
origins: ["San Diego, CA", foundlatlng],
destinations: gotoLoc,
travelMode: google.maps.TravelMode.WALKING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false,
}, callback); //end service.getdistancematrix()
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%
}
#map_canvas {
height: 400px;
width: 100%;
}
tr,
td,
tbody,
table {
height: 100%;
width: 100%;
}
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<table border="1">
<tr>
<td>
<div id="map_canvas"></div>
</td>
</tr>
<tr>
<td>
<div id="info"></div>
</td>
</tr>
</table>
Wouldn't it be so much more helpful if you could provide an Index/ID with each Origin and Destination that would be returned in the API response?
If the order is guaranteed to be the exact same as sent, I agree that this should work fine. But this is not stated as guaranteed and it seems to arbitrarily limit Google's ability to order the results in a way that suits them better.
I am trying to adapt this Google Maps distance calculator to my needs, but am not overly familiar with plain Javascript, and only Jquery.
I am trying to modify one of the destination variables so that it pulls it from a text box instead.
Usually the line reads :
var destinationA = 'pe219px';
But I am trying to change it to the following, usually I would do this with a keyup function to update the value as the person types in jquery, but im not sure what im doing in plain javascript. This is what I have come up with so far, but it doesn't appear to do a lot :
function setValue() {
destinationA=parseInt(document.getElementById('deliverypostcode').value);
}
This is the example I am trying to modify
https://developers.google.com/maps/documentation/javascript/examples/distance-matrix
This is the whole code :
<!DOCTYPE html>
<html>
<head>
<title>Distance Matrix service</title>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 100%;
width: 50%;
}
#content-pane {
float:right;
width:48%;
padding-left: 2%;
}
#outputDiv {
font-size: 11px;
}
</style>
<script>
var map;
var geocoder;
var bounds = new google.maps.LatLngBounds();
var markersArray = [];
var origin1 = new google.maps.LatLng(53.003604, -0.532764);
var origin2 = 'pe219px';
function setValue() {
destinationA=parseInt(document.getElementById('deliverypostcode').value);
}
var destinationB = new google.maps.LatLng(53.003604, -0.532764);
var destinationIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=D|FF0000|000000';
var originIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=O|FFFF00|000000';
function initialize() {
var opts = {
center: new google.maps.LatLng(53.003604, -0.532764),
zoom: 8
};
map = new google.maps.Map(document.getElementById('map-canvas'), opts);
geocoder = new google.maps.Geocoder();
}
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin1, origin2],
destinations: [destinationA, destinationB],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var outputDiv = document.getElementById('outputDiv');
outputDiv.innerHTML = '';
deleteOverlays();
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
addMarker(origins[i], false);
for (var j = 0; j < results.length; j++) {
addMarker(destinations[j], true);
outputDiv.innerHTML += origins[i] + ' to ' + destinations[j]
+ ': ' + results[j].distance.text + '<br>';
}
}
}
}
function addMarker(location, isDestination) {
var icon;
if (isDestination) {
icon = destinationIcon;
} else {
icon = originIcon;
}
geocoder.geocode({'address': location}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
bounds.extend(results[0].geometry.location);
map.fitBounds(bounds);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
icon: icon
});
markersArray.push(marker);
} else {
alert('Geocode was not successful for the following reason: '
+ status);
}
});
}
function deleteOverlays() {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
markersArray = [];
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="content-pane">
<div id="inputs">
<form name="form1" method="post" action="">
<label for="deliverypostcode">Your Postcode</label>
<input type="text" name="deliverypostcode" id="deliverypostcode">
</form>
<p><button type="button" onclick="calculateDistances();">Calculate
distances</button></p>
</div>
<div id="outputDiv"></div>
</div>
<div id="map-canvas"></div>
</body>
</html>
Your function setValue is never called.
What if you delete it and just place the following line at the begining of calculateDistances ?
var destinationA= document.getElementById('deliverypostcode').value;
This works for me. Also, you don't need to parseInt your text input. Geocoding converts strings to a lat/long coordinates.