google maps API v3 : computing distance between 2 points on a polyline - google-maps-api-3

I am a bit confused with my code and I don't really know which way to go.
Let's consider I have a car marker that is running through a polyline.
I change its position each 500 ms by setting a timer :
function animate() {
var p = polyline.GetPointAtDistance(distanceFromBeginning);
carMarker.setPosition(p);
distanceFromBeginning += step;
timerHandle = setTimeout("animate("+(distanceFromBeginning)+")", tick);
}
I also added the fact that my car can be dragged on the route :
google.maps.event.addDomListener(carMarker, 'dragend', function(e) {
var p = find_closest_point_on_path(e.latLng,polyline.getPath());
console.log("position is : " + p);
carMarker.setPosition(p);
console.log("dragend")
});
Now that I have a new position after dragging the car on the polyline, how can I get its distance from the start location so I can update it correctly in my timer?

Once you have the coordinates for the end location (lets call the "destination"), and assuming that on your 'dragend' event you set the coordinates for the car (let call "origin") location you can call this function on your listener:
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: [destination],
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;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
console.log(results[j].distance.text);
console.log(results[j].duration.text);
}
}
}
}
Check this example on jsfiddle based on the Google documentation(look the result on your console)
Fell free to reply if you need more help with this code or if it's not what you want.

Related

add context (this) to google maps request

I am developing this page for a site, that generates search results based on the current logged in user. My aim is to loop through every house and assign it a distance.
My issue is I cannot seem to use context (this) inside of a distance matrix request/response.
$('.houseWrapper').each(function() {
var origin = $(this).children('.houseMeta').attr('data-origin');
var destination = $(this).children('.houseMeta').attr('data-destination');
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
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) {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var element = results[j];
var distance = element.distance.text;
var duration = element.duration.text;
console.log($(this).html());
}
}
}
}
});
try :
var that = this;
var origin = $(this).children('.houseMeta').attr('data-origin');
....
Then later:
console.log($(that).html());
I would make "this" passed in as an argument to the function, kind of like how a partial function works.
var callback = function(this) {
return function(response, status) {
// ...
}
}(this);
there are 2 arguments that will be passed to the $.each()-callback, the index of the element and the element.
Just use these arguments:
$('.houseWrapper').each(function(index,node) {
//somewhere
console.log($(node).html());
});

Google Maps Javascript V3: remove a route, but keep other routes displayed

I've created the following testcase in JSFiddle: http://jsfiddle.net/4Wtb3/15/. When I check a checkbox for route A or route B, the routes are displayed. So far, so good ...
if (routes.length > 0) {
for (var i = 0; i < routes.length; i++) {
var route = routes[i];
var request = {
origin: route.origin,
destination: route.destination,
travelMode: google.maps.TravelMode.WALKING
};
var directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true,
preserveViewport: true,
polylineOptions: {
strokeColor: '#C6D300'
}
});
directionsDisplay.setMap(map);
directionsDisplays.push(directionsDisplay);
directionsService.route(request, function (result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
}
});
}
}
But when I uncheck them, I want to clear the selected route. I keep track of all directionDisplay's using an array (to put the map value to 'null'). First I clear everything, then I redraw every route which is still in the list.
The problem: routes are still in the map, even if I uncheck them ...
Any idea's what exactly is going wrong?
There is no length of array in for loop so setMap(null) is never called. Code should be changed from
if (directionsDisplays.length > 0) {
for(var i = 0; i < directionsDisplays; i++) {
directionsDisplays[i].setMap(null);
}
}
to
if (directionsDisplays.length > 0) {
for(var i = 0; i < directionsDisplays.length; i++) {
directionsDisplays[i].setMap(null);
}
}
...
And additional fix for closure problem:
// Draw all routes
if (routes.length > 0) {
for (var i = 0; i < routes.length; i++) {
(function(i){
var route = routes[i];
var request = {
origin: route.origin,
destination: route.destination,
travelMode: google.maps.TravelMode.WALKING
};
....
})(i);
}
}
Updated example at jsfiddle

Google Maps DistanceMatrix

I am using Google API, what I need to do is get two different distances in miles. At the moment I have the following:-
var start = arrObjLatLngs[0];
var end = arrObjLatLngs[arrObjLatLngs.length - 1];
var base = new google.maps.LatLng(52.781048888889, -1.2110222222222546);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [base, base],
destinations: [start, end],
travelMode: google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false
}, callback);
function callback(response, status) {
if (status == google.maps.DistanceMatrixStatus.OK) {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var element = results[j];
var distance = element.distance.text;
var duration = element.duration.text;
var from = origins[i];
var to = destinations[j];
}
}
}
}
What I need to have is two variables; $runinPickup and $runinDestination that contains the distance between 1.) base and start (which will be $runinPickup) and 2.) base and end (which will be $runinDestination)
If I alert distance I get the response:-
13.9 km
5.2 km
13.9 km
5.2 km
Firstly, I'm just wanting to know how I can get the distance of just the distance between base and start as $runinPickup. Secondly, is there a way I can do this so it doesn't include the decimal? So instead of 13.9 km for the first value, it would just be 13.
Then I would need to convert it into miles, which I'm guessing once I can get the value I would do it as follows:
var pickup_distance = parseInt(($fieldPickup / 8) * 5); ?
Any help would be much appreciated! :)
Did you read the documentation? Passing the same address twice in the origins array:
origins: [base, base],
destinations: [start, end],
Is going to give you the same result twice. This should work (not tested), and give you 2 results:
origins: [base],
destinations: [start, end],
To get miles I would suggest setting the unitSystem to IMPERIAL (although I can't find a definition of what that means in the documentation):
unitSystem (optional) — The unit system to use when displaying distance. Accepted values are:
google.maps.UnitSystem.METRIC (default)
google.maps.UnitSystem.IMPERIAL
You can of course convert METRIC units to miles.
Example showing the two values, with distances in IMPERIAL units. Modified from the example in the documentation.
code snippet:
var map;
var geocoder;
var bounds = new google.maps.LatLngBounds();
var markersArray = [];
var base = new google.maps.LatLng(55.930385, -3.118425);
var start = 'Greenwich, England';
var destinationA = 'Stockholm, Sweden';
var end = new google.maps.LatLng(50.087692, 14.421150);
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,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), opts);
geocoder = new google.maps.Geocoder();
calculateDistances();
}
google.maps.event.addDomListener(window, 'load', initialize);
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [base],
destinations: [start, end],
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 = '<table border="1">';
deleteOverlays();
var stringArray = ['$runinPickup', '$runinDestination'];
var htmlString = '<table border="1">';
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);
htmlString += '<tr><td>' + stringArray[j] + '</td><td>' + results[j].distance.text + '</td></tr>';
outputDiv.innerHTML += '<tr><td>' + stringArray[j] + '</td><td>' + results[j].distance.text + '</td></tr>';
}
}
htmlString += '</table>';
// outputDiv.innerHTML += '</table>';
outputDiv.innerHTML = htmlString;
// alert(htmlString);
}
}
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() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
}
}
body {
margin: 20px;
font-family: courier, sans-serif;
font-size: 12px;
}
#map {
height: 480px;
width: 640px;
border: solid thin #333;
margin-top: 20px;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="outputDiv"></div>
<div id="map"></div>

Javascript Pass Parameter to Callback or Set Variable Value in DistanceMatrixStatus

I have been playing a little bit with Google's DistanceMatrixService. The code below works, but, how can I pass another parameter to the callback function or grab one of the values out of the callback?
For example: I have two divs that I want to show different results in (Results1 and Results2), so I am thinking I need to either
pass another value to the GoogleMapDistance function like GoogleMapDistance(YourLatLong,DestLatLong,TheDiv)
or
be able to grab the ResultStr externally outside of the callback document.getElementById("Results1").innerHTML = ResultStr;
or
set the innerHTM to the returned value of the function document.getElementById("Results1").innerHTML = GoogleMapDistance(YourLatLong,DestLatLong);
I'm stuck. How can I do accomplish this? The way it looks right now is that I am only going to be able to run all this code once and have it only write to one div.
<div id="Results1"></div>
<div id="Results2"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
function GoogleMapDistance(YourLatLong,DestLatLong)
{
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [YourLatLong],
destinations: [DestLatLong],
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)
{
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++)
{
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++)
{
var element = results[j];
var from = origins[i];
var to = destinations[j];
var distance = element.distance.text;
var duration = element.duration.text;
var ResultStr = distance + " (<i>" + duration + "</i>)";
}
}
document.getElementById("Results1").innerHTML = ResultStr;
}
}
var YourLatLong = "45.4049,-122.797997";
var DestLatLong1 = "47.468893,-122.227978";
var DestLatLong2 = "61.221274,-149.831545";
GoogleMapDistance(YourLatLong,DestLatLong1);
</script>
You can't change how Google calls the callback, but you can let it call your own locally function as the callback and then have that (via a closure) call another callback after adding the desired extra argument like this:
function GoogleMapDistance(YourLatLong,DestLatLong, item)
{
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [YourLatLong],
destinations: [DestLatLong],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, function(response, status) {callback(response, status, item)});
}
Or, you could just define your callback inline so it has access to the parent function variables directly:
function GoogleMapDistance(YourLatLong,DestLatLong, item)
{
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [YourLatLong],
destinations: [DestLatLong],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, function callback(response, status)
{
// you can access the parent scope arguments like item here
if (status == google.maps.DistanceMatrixStatus.OK)
{
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++)
{
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++)
{
var element = results[j];
var from = origins[i];
var to = destinations[j];
var distance = element.distance.text;
var duration = element.duration.text;
var ResultStr = distance + " (<i>" + duration + "</i>)";
}
}
document.getElementById("Results1").innerHTML = ResultStr;
}
}
)}

distance matrix google maps javascript api3

I play with distance matrix
http://code.google.com/apis/maps/documentation/javascript/services.html#distance_matrix
to get the duration from one origin to multiple destinations.
I have this code:
var duration = new Array();
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: destination,
travelMode: google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false
},
function(response, status)
{
if (status == google.maps.DistanceMatrixStatus.OK)
{
var destinations = response.destinationAddresses;
var results = response.rows[0].elements;
for (var j = 0; j < results.length; j++)
duration[j] = results[j].duration.value;
}
});
alert(duration[0]);
but i have alert "undefined". when i put the alert command inside the callback function i have the alert i want. why is that??? how can i fix it?
Thank u in advance!
var duration = new Array();
function calculate_distance(){
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: destination,
travelMode: google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false
},
function(response, status)
{
if (status == google.maps.DistanceMatrixStatus.OK)
{
var destinations = response.destinationAddresses;
var results = response.rows[0].elements;
for (var j = 0; j < results.length; j++)
duration[j] = results[j].duration.value;
}
});
}
google.maps.event.addListener(autocomplete, 'place_changed', calculate_distance);
alert(duration[0]);
Try anything like that
Move the alert in to the callback. The function is a callback that is executed asynchronously.

Resources