Google Maps API - Getting closest points to zipcode
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