Google Maps Places Search, calculate distance to each result - javascript

I'm currently making an app for a university assignment. I'm using the google maps places api and gmaps.js.
What I want to do is let user search places and show the results in a simple list (which I've got working) but I want to calculate the distance to each of the search results as well, which is sort of working (I think!) but I'm not sure how to make it display how I want, e.g:
"Search Result - 1.1 mi away"
"Search Result - 0.8 mi away"
What it is doing right now is calculating the distances but all the values are being set next to all of the search results, instead of next to each other. In one line (all bunched together).
(Had to remove a link to post a new one)
I don't know how to split them or do it more cleanly from the start. I think the problem lies in the function which is calculating the distances using "google.maps.DistanceMatrixService".
var origin = currentLocation;
var destination = place.geometry.location;
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.WALKING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, getDistance);
function getDistance(response, status) {
if (status == "OK") {
var distance = response.rows[0].elements[0].distance.text;
console.log(distance);
$(".distance").append(distance);
} else {
return false;
console.log(response + status)
}
}
getDistance();
This line is my best guess:
response.rows[0].elements[0].distance.text;
But I'm quite lost with it.
Full code of my search request:
$("#place-search").submit(function(e){
e.stopPropagation(); e.preventDefault();
var query = $("#place-query").val();
map.addLayer("places", {
location: cheltenham, //new google.maps.LatLng(51.902707,-2.073361),
radius: 500, //experiment with the distance (in metres)
query: query,
opennow: true,
textSearch: function (results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
$(".results-list").html(""); //remove previous results
removeMarkers(); //remove previous markers
var bounds = new google.maps.LatLngBounds();
//console.log(bounds);
//I think if we set i to say 10, it will limit the search results - by default the places api returns 20 result sets
for (var i = 0; i < results.length; i++) {
//console.log(i);
var place = results[i];
var image = { //set to better sizes and positions (icons from search results)
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
/* ---------- */
var origin = currentLocation; //new google.maps.LatLng(51.902707,-2.073361);
var destination = place.geometry.location; //new google.maps.LatLng(51.899464, -2.074641);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.WALKING, //this needs to be a choice
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, getDistance);
function getDistance(response, status) {
if (status == "OK") {
var distance = response.rows[0].elements[0].distance.text; //the one I need
console.log(distance);
$(".distance").append(distance);
} else {
return false;
console.log(response + status)
}
}
getDistance();
/* ---------- */
map.addMarker({
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
icon: image,
animation: google.maps.Animation.DROP,
title: place.name,
//we need to style and build these better - ideas? should be simple I think, Name + Location + Image
infoWindow: {
content: '<h2>'+place.name+'</h2>' + '<p>Rating: '+place.rating+'</p>' + '<p>'+(place.vicinity ? place.vicinity : place.formatted_address)+'</p><img src="'+place.icon+'"" width="100"/>'
}
});
bounds.extend(place.geometry.location);
$(".results-list").append("<li>" + place.name + "<span class=\"distance\"></span></li>");
}
map.fitBounds(bounds); //fit to the new bounds
}//end if search OK
}
});
});
Any help or pointers would be greatly appreciated!
Update:
I've tried moving the line that puts the items into the list with jQuery into the function getDistance(), and that ends up putting the distances with the place name but it's the same place name for every distance that is calculated. It is the last result from the search.
getDistance()
function getDistance(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];
$(".results-list").append("<li><span class=\"name\">" + place.name + "</span>" + distance + "</li>")
}
}
} else {
return false;
console.log(response + status)
}
}
What the output looks like: http://i.imgur.com/FSCMMzF.png
Thanks to everyone who's taken a look so far!

Related

How to parse Distance Matrix in JS to only get the distance and the duration?

I have been trying to only get the distance and duration using the Google Distance Matrix API.
I tried and built and modified as I logically could but nothing.
I even slice the response because I did not succeed to parse it.
I have multiple approaches but let show two script use.
function calculateDistance() {
var origin = $('#origin').val();
var destination = $('#destination').val();
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL, // Miles and feet.
// unitSystem: google.maps.UnitSystem.metric, // Kilometers and meters.
avoidHighways: false,
avoidTolls: false
}, callback);
}
// Get distance results.
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
$('#result').html(err);
} else {
var origin = response.originAddresses[0];
var destination = response.destinationAddresses[0];
if (response.rows[0].elements[0].status === "ZERO_RESULTS") {
$('#result').html("Better use a plane. There are no roads between " + origin + " and " + destination);
} else {
var distance = response.rows[0].elements[0].distance;
var duration = response.rows[0].elements[0].duration;
console.log(response.rows[0].elements[0].distance);
var distance_in_kilo = distance.value / 1000; // The kilometer.
var distance_in_mile = distance.value / 1609.34; // The mile.
var duration_text = duration.text;
var duration_value = duration.value;
$('#in_mile').text(distance_in_mile.toFixed(2));
$('#in_kilo').text(distance_in_kilo.toFixed(2));
$('#duration_text').text(duration_text);
$('#duration_value').text(duration_value);
$('#from').text(origin);
$('#to').text(destination);
}
}
}
The second one:
<script>
// #ts-nocheck TODO remove when fixed
function initMap() {
const bounds = new google.maps.LatLngBounds();
const markersArray = google.maps.Marker = [];
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: 55.53,
lng: 9.4
},
zoom: 10,
});
// Initialize services.
const geocoder = new google.maps.Geocoder();
const service = new google.maps.DistanceMatrixService();
// Build request.
const origin2 = "634 Pretorius street, Pretoria, South Africa";
const destinationA = "263 luttig street, Pretoria, South Africa";
const request = {
origins: [origin2],
destinations: [destinationA],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false,
};
// Put request on page.
document.getElementById("request").innerText =
JSON.stringify(request),
// Get distance matrix response.
service.getDistanceMatrix(request).then((response) => {
// Put response.
document.getElementById("response").innerHTML = JSON.stringify(response);
});
}
function myDistance() {
const x = document.getElementById("response").innerHTML;
// const y = x.slice(43, 70);
// JSON.parse(x);
var y = x.rows[0].elements[0].distance.text;
document.getElementById("distance").innerHTML = y;
}
</script>
I tried both script above.
I want to only get the distance in km an the duration in minutes.

Google Direction service giving wrong route

Drawing googlemap route on map with below coordinates.But getting wrong route. Where is the issue?
LNG LAT
58.5589893333333 23.6229513333333 Start
58.5589985 23.6231225 WAY POINT 1
58.5591366666667 23.6235491666667 WAY POINT 2
58.55882 23.6236481666667 WAY POINT 3
58.5476361666667 23.6209141666667 WAY POINT 4
58.5454098333333 23.616038 END
the wrong route
Same coordinates tried in Google map website,It is giving correct way
Where is the problem? Sending all the waypoints, origin and destination correctly. The coordinates are from tracking devices. only some cases showing wrong route like this.
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
var first = new google.maps.LatLng(23.6231225,58.5589985);
var second = new google.maps.LatLng(23.6235491666667,58.5591366666667);
var third = new google.maps.LatLng(23.6236481666667,58.55882);
var forth = new google.maps.LatLng(23.6209141666667,58.5476361666667);
var i = 0;
var start = StartlatDir[i]+','+StartlongDir[i];
var end = EndlatDir[i] + ',' + EndlongDir[i];
var request = {
origin: start,
destination: end,
waypoints: [{ location:first, stopover: false },
{ location: second, stopover: false },
{ location: third, stopover: false },
{ location: forth, stopover: false }],
optimizeWaypoints: false,
travelMode: google.maps.DirectionsTravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var myRoute = response.routes[0];
var txtDir = '';
for (var i = 0; i < myRoute.legs[0].steps.length; i++) {
txtDir += myRoute.legs[0].steps[i].instructions + "<br />";
}
}
});
The DirectionsService is very sensitive to waypoints near exits (or on the wrong side of the road).
Waypoint 4 (23.6209141666667, 58.5476361666667) makes the route take the exit.
Moving it further along the road to (23.620315,58.5471) gives the expected route:
fiddle
or removing it completely gives the expected route
fiddle

Google Maps JavaScript API calculate distance to each marker [duplicate]

I'm in the process of adding a map to a website using Google Maps API v3 and javascript.
I have a list of addresses and have successfully plotted them on the map. When the user types in a zip code, the map re-centers on their location showing the markers closest to that point. Now, I need to create a list view of the closest 3 or 5 locations to their zip code with links for driving direction. I'm stuck...and open for suggestions.
The usual solution is to use the google.maps.geometry.spherical library computeDistanceBetween(from:LatLng, to:LatLng, radius?:number) method to reduce the number to about 10, then use the distance matrix return the driving distance to those locations so the results can be sorted by driving distance (actual travel distance), and reduced to the closest 3 to 5 locations by actual travel distance within the request limits.
example (finds the 3 closest places from a list)
(data borrowed from the FusionTables "pizza store" example)
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
if (customerMarker) customerMarker.setMap(null);
customerMarker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
closest = findClosestN(results[0].geometry.location,10);
// get driving distance
closest = closest.splice(0,3);
calculateDistances(results[0].geometry.location, closest,3);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
function findClosestN(pt,numberOfResults) {
var closest = [];
document.getElementById('info').innerHTML += "processing "+gmarkers.length+"<br>";
for (var i=0; i<gmarkers.length;i++) {
gmarkers[i].distance = google.maps.geometry.spherical.computeDistanceBetween(pt,gmarkers[i].getPosition());
document.getElementById('info').innerHTML += "process "+i+":"+gmarkers[i].getPosition().toUrlValue(6)+":"+gmarkers[i].distance.toFixed(2)+"<br>";
gmarkers[i].setMap(null);
closest.push(gmarkers[i]);
}
closest.sort(sortByDist);
return closest;
}
function sortByDist(a,b) {
return (a.distance- b.distance)
}
function calculateDistances(pt,closest,numberOfResults) {
var service = new google.maps.DistanceMatrixService();
var request = {
origins: [pt],
destinations: [],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
};
for (var i=0; i<closest.length; i++) request.destinations.push(closest[i].getPosition());
service.getDistanceMatrix(request, function (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('side_bar');
outputDiv.innerHTML = '';
var results = response.rows[0].elements;
for (var i = 0; i < numberOfResults; i++) {
closest[i].setMap(map);
outputDiv.innerHTML += "<a href='javascript:google.maps.event.trigger(closest["+i+"],\"click\");'>"+closest[i].title + '</a><br>' + closest[i].address+"<br>"
+ results[i].distance.text + ' appoximately '
+ results[i].duration.text + '<br><hr>';
}
}
});
}
example above with "Get Directions" link in the infoWindow
When you have the lat lng pair of a zipcode you can use the harversine formula to find the distance from your location.

Google Map doesn't loads properly in ligh box pop up

I have two textbox in which we can enter locations & on button click route between two points shows in the map. Problem is on page it shows properly but when I use lighbox popup then map only shows grey color like below image. For pop up box I have used asp.net control modalpopupextender.
JS Code.
<script type="text/javascript">
var source, destination;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
google.maps.event.addDomListener(window, 'load', function () {
new google.maps.places.SearchBox(document.getElementById('txtSource'));
new google.maps.places.SearchBox(document.getElementById('txtDestination'));
directionsDisplay = new google.maps.DirectionsRenderer({ 'draggable': true });
});
function GetRoute() {
debugger;
var mumbai = new google.maps.LatLng(18.9750, 72.8258);
var mapOptions = {
zoom: 7,
center: mumbai
};
map = new google.maps.Map(document.getElementById('dvMap'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('dvPanel'));
//*********DIRECTIONS AND ROUTE**********************//
source = document.getElementById("txtSource").value;
destination = document.getElementById("txtDestination").value;
var request = {
origin: source,
destination: destination,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
//*********DISTANCE AND DURATION**********************//
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
var distance = response.rows[0].elements[0].distance.text;
var distance2 = response.rows[0].elements[0].distance.text; /*used for ID firstNumber*/
var duration = response.rows[0].elements[0].duration.text;
var dvDistance = document.getElementById("dvDistance");
var firstNumber = document.getElementById("firstNumber");
var dvDuration = document.getElementById("dvDuration");
var dvDurationC = document.getElementById("dvDurationC")
dvDistance.innerHTML = "";
dvDistance.value = parseFloat(distance);
firstNumber.innerHTML = distance2 /*used for ID firstNumber*/
dvDuration.innerHTML = duration;
} else {
alert("Unable to find the distance via road.");
}
});
}
</script>
Try making these two changes:
Remove the display property and set visibility: hidden on #map.
Move #map to a place where the space it inhabits won’t be noticed. Right before is probably a good choice.
Refer to this tutorial.

google maps route in ASP

I need to get a route between 2 location in asp, since I want variables to improve my page navigation. I found an excellent method online that works wonders, but it activates a onclick function to work. I need to reload the page to obtain variables from my database.
The original version is this one:
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<script type="text/javascript">
var source, destination;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
google.maps.event.addDomListener(window, 'load', function () {
new google.maps.places.SearchBox(document.getElementById('txtSource'));
directionsDisplay = new google.maps.DirectionsRenderer({ 'draggable': true });
});
function GetRoute() {
var rome = new google.maps.LatLng(41.918357, 12.485029);
var mapOptions = {
zoom: 4,
center: rome
};
map = new google.maps.Map(document.getElementById('dvMap'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('dvPanel'));
//*********DIRECTIONS AND ROUTE**********************//
source = document.getElementById("txtSource").value;
destination = document.getElementById("txtDestination").value;
var request = {
origin: source,
destination: destination,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
//*********DISTANCE AND DURATION**********************//
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
var distance = response.rows[0].elements[0].distance.text;
var duration = response.rows[0].elements[0].duration.text;
var dvDistance = document.getElementById("dvDistance");
dvDistance.innerHTML = "";
dvDistance.innerHTML += "<strong>" + "Distanza:" + "</strong>" + " " + distance + "<br />";
dvDistance.innerHTML += "<strong>" + "Durata:" + "</strong>" + " " + duration;
} else {
alert("Impossibile trovare la distanza stradale");
}
});
}
</script>
it's activated by a onclick="GetRoute()" command in the request form, where I input my departure and destination in two fields. It will then display a map with the two locations with the route informations by its side.
Now, what I want, is to activate it with asp, since I need to access my sql.So the button type will become a submit without the onclick instruction, the page will reload, I'll get the data I need questioning my database and the gmaps script will run as usual, automatically triggering that GetRoute() function. I hope I've been clear, my english is a bit rusty, I could provide the work in progress address where I'm trying to fix this bad boy.
I'd like the whole script to be activated automatically after the page is reloaded, without the onclick command. So, basically, I want to get rid of the GetRoute() command. As long as I have the data needed by the script (txtSource and txtDestination), is there a way to obtain my map and route, once the page has reloaded?
You could do this with a slight modification to your existing code,
using the GetRoute function, without the onclick:
In the GetRoute function, set the source and destination variables to the request values:
function GetRoute()
{
source = "<%=Request("txtSource")%>";
destination = "<%=Request("txtDestination")%>";
if( source != "" && destination != "")
{
/*the rest of your code as is,except the following change:
comment out the following two lines, as we are already setting this with the request values
source = document.getElementById("txtSource").value;
destination = document.getElementById("txtDestination").value;
*/
}
}
And in the html, for the body tag, add <body onload="GetRoute();"> so that the function will be called after all the elements are loaded.
thank you for your help. I used your suggestions and the map appears, but without the route, so maybe I did something wrong in the code. I can confiirm that the two requests (txtsource and txtdestination) are passed correctly.
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script><script type="text/javascript">
var source, destination;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
google.maps.event.addDomListener(window, 'load', function () {
new google.maps.places.SearchBox(document.getElementById('txtSource'));
new google.maps.places.SearchBox(document.getElementById('txtDestination'));
directionsDisplay = new google.maps.DirectionsRenderer({ 'draggable': true });
});
function GetRoute()
{
source = "<%=Request.form("txtSource")%>";
destination = "<%=Request.form("txtDestination")%>";
if( source != "" && destination != "")
{
var rome = new google.maps.LatLng(41.918357, 12.485029);
var mapOptions = {
zoom: 4,
center: rome
};
map = new google.maps.Map(document.getElementById('dvMap'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('dvPanel'));
//*********DIRECTIONS AND ROUTE**********************//
/*source = document.getElementById("txtSource").value;
destination = document.getElementById("txtDestination").value;
*/
var request = {
origin: source,
destination: destination,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
//*********DISTANCE AND DURATION**********************//
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
origins: [source],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
var distance = response.rows[0].elements[0].distance.text;
var duration = response.rows[0].elements[0].duration.text;
var dvDistance = document.getElementById("dvDistance");
dvDistance.innerHTML = "";
dvDistance.innerHTML += "<strong>" + "Distanza:" + "</strong>" + " " + distance + "<br />";
dvDistance.innerHTML += "<strong>" + "Durata:" + "</strong>" + " " + duration;
} else {
alert("Impossibile trovare la distanza stradale");
}
});
}
}
</script>
Edit: I have divs in my HTML for the map and the route. That doesn't appear to be the problem, since the map shows, but I have no route on it
<div class="row">
<div class="col-md-6">
<div id="dvMap" style="height: 500px"></div>
</div>
<div class="col-md-6" style="height:500px; overflow-x:hidden; overflow-y:auto;">
<div id="dvPanel" ></div>
</div>

Categories

Resources