I have this working, just one "origin" marker and multiple dynamic "destination" markers:
markerOrigin = place.geometry.location;
for (var i = 0; i < markers.length; i++) {
markersPosition = markers[i].getPosition();
alert(markersPosition); //give me all the markers latlng
}
service.getDistanceMatrix({
origins: [markerOrigin],
destinations: [markersPosition],
travelMode: 'DRIVING',
Why am i just getting one of the destination markers?
If you want multiple results, you need to pass an array with multiple entries in to the service for the destinations property. Currently you are passing in [markersPosition] (where markersPosition contains a single position).
Change markersPosition to an array:
var markersPosition = [];
Push each marker's location onto it:
for (var i = 0; i < markers.length; i++) {
markersPosition.push(markers[i].getPosition());
}
Then pass that into the service as the destinations property:
service.getDistanceMatrix({
origins: [markerOrigin],
destinations: markersPosition,
travelMode: 'DRIVING'
proof of concept fiddle
code snippet:
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#map {
height: 75%;
}
<div id="output"></div>
<div id="map"></div>
<script>
function initMap() {
var myLatLng = {
lat: 42.31391,
lng: -83.2032224
};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatLng,
mapTypeId: 'hybrid'
});
markerOrigin = myLatLng;
var locations = [
{address: "16099 Michigan Ave, Dearborn, MI 48126, USA", lat: 42.31391, lng: -83.2032224},
{address: "Dearborn, MI, USA", lat: 42.3222599, lng: -83.1763145},
{address: "Dearborn, MI 48126, USA", lat: 42.3382755, lng: -83.1756188},
{address: "Wayne County, MI, USA", lat: 42.2790746, lng: -83.336188},
{address: "Detroit Metropolitan Area, MI, USA", lat: 42.8105356, lng: -83.0790865},
{address: "Michigan, USA", lat: 44.3148443, lng: -85.6023643}
]
var markers = [];
for (var i = 0; i < locations.length; i++) {
var marker = new google.maps.Marker({
position: locations[i],
map: map
});
markers.push(marker);
}
var markersPosition = [];
for (var i = 0; i < markers.length; i++) {
markersPosition.push(markers[i].getPosition());
// alert(markersPosition); //give me all the markers latlng
}
var service = new google.maps.DistanceMatrixService;
service.getDistanceMatrix({
origins: [markerOrigin],
destinations: markersPosition,
travelMode: 'DRIVING'
}, function(response, status) {
if (status !== 'OK') {
alert('Error was: ' + status);
} else {
var originList = response.originAddresses;
var destinationList = response.destinationAddresses;
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
};
for (var i = 0; i < originList.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
outputDiv.innerHTML += originList[i] + ' to ' + destinationList[j] +
': ' + results[j].distance.text + ' in ' +
results[j].duration.text + '<br>';
}
}
});
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
Related
I am trying to get the nearest marker to the user location and then get directions on button click, I have passed the markers to getDirections(markers) but when the function google.maps.geometry.spherical.computeDistanceBetween takes the google.maps.LatLng object throws the error Uncaught TypeError: Cannot read property 'lat' of undefined
But the markers array and the userLocation are both OK with the data (not undefined) so I can't understand what is going on.
The code:
jQuery(document).ready(function () {
// Create the script tag, set the appropriate attributes
let script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyBMCq6Fj4pN0Ku5ScVza28FZw0beM&callback=initMap&libraries=places&libraries=geometry';
script.defer = true;
var map
let infowindow
window.initMap = function () {
const center = {
lat: -36.561551,
lng: -72.0954877
}
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: center
});
let markers = setMarkers(map)
getDirections(markers)
}
const locations = [
['Super Pellet Santiago', -33.458717664930084, -70.77513497336462],
['Super Pellet Chillan', -36.561551, -72.0954877],
['Super Pellet Concepción', -36.8158124, -73.0741686],
['Super Pellet Los Angeles', -37.4774907, -72.3245759],
['Super Pellet Angol', -33.80010128657071, 151.28747820854187],
['Super Pellet Temuco', -38.7702088, -72.6301967]
];
function setMarkers(map) {
let markers = []
for (let i = 0; i < locations.length; i++) {
markers[i] = new google.maps.Marker({
title: locations[i][0],
position: {
lat: locations[i][1],
lng: locations[i][2]
},
map: map
});
google.maps.event.addListener(markers, 'click', (function (markers, i) {
return function () {
infowindow.setContent(locations[i][0]);
infowindow.open(map, markers);
}
})(markers, i));
}
return markers
// Append the 'script' element to 'head'
}
document.head.appendChild(script);
function getDirections(markers) {
let userLocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success,error)
function success(position){
userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
}
function error(){
alert("Debes activar la geolocalización")
}
}
//Get directions to nearest marker
jQuery('#FINDPOS').click(() => {
if(typeof(userLocation) === 'undefined'){
alert("Debes permitir la localización")
}
else{
let uLocation = new google.maps.LatLng(userLocation.lat,userLocation.lng)
let distances = [];
let closest = -1;
if(markers.length > 0){
for (i = 0; i < markers.length; i++) {
var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].position, uLocation.position);
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
alert('Closest marker is: ' + markers[closest].getTitle());
}
}
})
}
})
Your uLocation variable is a google.maps.LatLng object, it doesn't have a .position property (for that matter, the .position property of google.maps.Marker objects isn't documented, it would be safer to call the (documented) .getPosition() method on the markers)
var d = google.maps.geometry.spherical.computeDistanceBetween(
markers[i].position, uLocation.position);
should be:
var d = google.maps.geometry.spherical.computeDistanceBetween(
markers[i].getPosition(), uLocation);
related questions:
Google Maps API - Getting closest points to zipcode
Google Maps API - Closest marker function change to closest n markers
proof of concept fiddle
code snippet:
jQuery(document).ready(function() {
// Create the script tag, set the appropriate attributes
let script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places&libraries=geometry';
script.defer = true;
var map
let infowindow
window.initMap = function() {
const directionsRenderer = new google.maps.DirectionsRenderer();
const center = {
lat: -36.561551,
lng: -72.0954877
}
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: center
});
let markers = setMarkers(map)
directionsRenderer.setMap(map);
getDirections(markers, directionsRenderer)
}
const locations = [
['Super Pellet Santiago', -33.458717664930084, -70.77513497336462],
['Super Pellet Chillan', -36.561551, -72.0954877],
['Super Pellet Concepción', -36.8158124, -73.0741686],
['Super Pellet Los Angeles', -37.4774907, -72.3245759],
['Super Pellet Angol', -33.80010128657071, 151.28747820854187],
['Super Pellet Temuco', -38.7702088, -72.6301967]
];
function setMarkers(map) {
let markers = []
for (let i = 0; i < locations.length; i++) {
markers[i] = new google.maps.Marker({
title: locations[i][0],
position: {
lat: locations[i][1],
lng: locations[i][2]
},
map: map
});
google.maps.event.addListener(markers, 'click', (function(markers, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, markers);
}
})(markers, i));
}
return markers
// Append the 'script' element to 'head'
}
document.head.appendChild(script);
function getDirections(markers, directionsRenderer) {
let userLocation = {
lat: -32.8894587,
lng: -68.8458386
}; // Mendoza, Capital Department, Mendoza Province, Argentina (-32.8894587, -68.8458386)
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success, error)
function success(position) {
userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
}
function error() {
document.getElementById('output').innerHTML = "Debes activar la geolocalización<br>defaulting to:Mendoza, Capital Department, Mendoza Province, Argentina (-32.8894587, -68.8458386)";
}
}
//Get directions to nearest marker
jQuery('#FINDPOS').click(() => {
if (userLocation === 'undefined') {
alert("Debes permitir la localización")
} else {
let uLocation = new google.maps.LatLng(userLocation.lat, userLocation.lng);
let distances = [];
let closest = -1;
if (markers.length > 0) {
for (i = 0; i < markers.length; i++) {
var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].getPosition(), uLocation);
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
document.getElementById('output').innerHTML = 'Closest marker is: ' + markers[closest].getTitle();
calculateAndDisplayRoute(uLocation, markers[closest].getPosition(), directionsRenderer);
}
}
})
}
})
function calculateAndDisplayRoute(start, end, directionsRenderer) {
const directionsService = new google.maps.DirectionsService();
directionsService.route({
origin: start,
destination: end,
travelMode: google.maps.TravelMode.DRIVING,
},
(response, status) => {
if (status === "OK") {
directionsRenderer.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: 90%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<input id="FINDPOS" value="FINDPOS" type="button" />
<div id="output"></div>
<div id="map"></div>
</body>
</html>
I am a JavaScript beginner, but I'm trying to put a route on a google maps with the Google Maps Directions API and Google Maps Javascript API. If I start the website it doesn't show me any route, but if I execute the commands at the Google Chrome Console it shows me the route. picture from the Google Chrome Console
<html>
<body>
<div id="map" style="width:100%;height:500px;"></div>
<script>
function requestRoute(origin1, origin2, destination1, destination2, waypoints) {
var directionsService = new google.maps.DirectionsService();
var myoutput = [];
var request = {
origin: new google.maps.LatLng(origin1, origin2),
destination: new google.maps.LatLng(destination1, destination2),
waypoints: waypoints,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function (result, status)
{ if (status == google.maps.DirectionsStatus.OK)
{
for (var x = 0; x < result.routes[0].legs.length; x++){
var myRoute = result.routes[0].legs[x];
for (var i = 0; i < myRoute.steps.length; i++) {
for (var j = 0; j < myRoute.steps[i].lat_lngs.length; j++) {
myoutput.push(myRoute.steps[i].lat_lngs[j]);
}
}
}
} else{
alert(status)
}
});
return myoutput;
};
function processWaypoints(waypoints) {
var myarray = waypoints;
var myoutput = []
for (var x = 0; x < waypoints.length; x++){
myoutput.push({location: new google.maps.LatLng(myarray[x][0], myarray[x][1]), stopover: false});
};
return myoutput;
};
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: {lat: 12, lng: 15},
scrollwheel: false
});
var waypoints1 = processWaypoints([[-34.6036844, -58.3815591]]);
var points1 = requestRoute(-33.4488897, -70.6692655, -24.7821269, -65.4231976, waypoints1);
var routLine1 = new google.maps.Polyline(
{
path: points1,
strokeColor: "#FFC107",
strokeOpacity:0.8,
strokeWeight:4
}
);
routLine1.setMap(map);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key='MyGoogleMapsAPIKey'&callback=initMap">
</script>
</body>
</html>
Has anybody an idea what is wrong in my code?
The problem you're having is that the directionsService call is asynchronous. at the time myoutput is returned from requestRoute it is still an empty array. I restructured:
<html>
<body>
<div id="map" style="width:100%;height:500px;"></div>
<script>
var map;
function requestRoute(origin1, origin2, destination1, destination2, waypoints) {
var directionsService = new google.maps.DirectionsService();
var myoutput = [];
var request = {
origin: new google.maps.LatLng(origin1, origin2),
destination: new google.maps.LatLng(destination1, destination2),
waypoints: waypoints,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function (result, status)
{ if (status == google.maps.DirectionsStatus.OK)
{
for (var x = 0; x < result.routes[0].legs.length; x++){
var myRoute = result.routes[0].legs[x];
for (var i = 0; i < myRoute.steps.length; i++) {
for (var j = 0; j < myRoute.steps[i].lat_lngs.length; j++) {
myoutput.push(myRoute.steps[i].lat_lngs[j]);
}
}
}
plotRoute(myoutput);
} else{
alert(status)
}
});
// return myoutput;
};
function processWaypoints(waypoints) {
var myarray = waypoints;
var myoutput = []
for (var x = 0; x < waypoints.length; x++){
myoutput.push({location: new google.maps.LatLng(myarray[x][0], myarray[x][1]), stopover: false});
};
return myoutput;
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: {lat: 12, lng: 15},
scrollwheel: false
});
var waypoints1 = processWaypoints([[-34.6036844, -58.3815591]]);
requestRoute(-33.4488897, -70.6692655, -24.7821269, -65.4231976, waypoints1);
}
function plotRoute(points1){
var routLine1 = new google.maps.Polyline(
{
path: points1,
strokeColor: "#FFC107",
strokeOpacity:0.8,
strokeWeight:4
}
);
routLine1.setMap(map);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAJLxeMko3jmj7ImPv96sVt-eyP7FtixQc&callback=initMap">
</script>
it's not pretty, but you get the idea.
Here I am calculating the distance and time between two latitude and longitude points.Almost I am getting the answer but I am not able to return the value to the function.
Please help me. Thanks in advance
My codings are :
function initMap() {
console.log(getDistanceandTime(srcRouteAddress.lat,srcRouteAddress.lng,destRouteAddress.lat,destRouteAddress.lng));
function getDistanceandTime(lat1,lon1,lat2,lon2){
var origin = {lat: parseFloat(lat1), lng: parseFloat(lon1)};
var destination = {lat: parseFloat(lat2), lng: parseFloat(lon2)};
var service = new google.maps.DistanceMatrixService;
//var test = [];
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING
}, function (response, status) {
if (status == google.maps.DistanceMatrixStatus.OK) {
var test_values = [];
var originList = response.originAddresses;
for (var i = 0; i < originList.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var test = results[j].distance.text + ' in ' + results[j].duration.text;
test_values.push(test);
console.log(test_values);
}
}
return test_values;
}
return test_values;
});
}
}
if it is a synchronous call, then try this, your var test_values = []; should be outside if (status == google.maps.DistanceMatrixStatus.OK) condition. And most probably insideif (status == google.maps.DistanceMatrixStatus.OK) is not executing
also google.maps.DistanceMatrixStatus.OK is asynchronous so better to return value inside if(google.maps.DistanceMatrixStatus.OK)
So try this
function initMap() {
console.log(getDistanceandTime(srcRouteAddress.lat,srcRouteAddress.lng,destRouteAddress.lat,destRouteAddress.lng));
function getDistanceandTime(lat1,lon1,lat2,lon2){
var origin = {lat: parseFloat(lat1), lng: parseFloat(lon1)};
var destination = {lat: parseFloat(lat2), lng: parseFloat(lon2)};
var service = new google.maps.DistanceMatrixService;
//var test = [];
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING
}, function (response, status) {
var test_values = [];
if (status == google.maps.DistanceMatrixStatus.OK) {
var originList = response.originAddresses;
for (var i = 0; i < originList.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var test = results[j].distance.text + ' in ' + results[j].duration.text;
test_values.push(test);
console.log(test_values);
}
}
return test_values;
}
});
}
}
Try this..
var test_values = []; // global variable
function initMap() {
// your code here
}
function showLatLng(){
console.log(test_values); // will output the content
}
Javascript runs on the UI thread; if your code waits for the server to reply, the browser must remain frozen. Ajax jquery async return value
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.
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>