98

When i click on map, which will be best way to find nearest marker or markers? is there some functions in api that will help me to do that?

it's google map api v3.

2
  • 1
    Do you use any database to store the coords of the markers? Commented Oct 30, 2010 at 8:14
  • sure, markers positions are stored in mysql datbase. Commented Oct 31, 2010 at 11:11

7 Answers 7

116

First you have to add the eventlistener

google.maps.event.addListener(map, 'click', find_closest_marker); 

Then create a function that loops through the array of markers and uses the haversine formula to calculate the distance of each marker from the click.

function rad(x) {return x*Math.PI/180;} function find_closest_marker( event ) { var lat = event.latLng.lat(); var lng = event.latLng.lng(); var R = 6371; // radius of earth in km var distances = []; var closest = -1; for( i=0;i<map.markers.length; i++ ) { var mlat = map.markers[i].position.lat(); var mlng = map.markers[i].position.lng(); var dLat = rad(mlat - lat); var dLong = rad(mlng - lng); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong/2) * Math.sin(dLong/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; distances[i] = d; if ( closest == -1 || d < distances[closest] ) { closest = i; } } alert(map.markers[closest].title); } 

This keeps track of the closest markers and alerts its title.

I have my markers as an array on my map object

Sign up to request clarification or add additional context in comments.

9 Comments

Not to open up an old thread, but I have tried to implement this, and it seems to search eastward rather then finding the closest. So if I search for a location, it will search to the eastward and find the closest that way, even if there is a REAL close on the the west. Does that make sense?
@Lee - it makes sense, but i can't duplicate the issue
Yeah this didn't work at all for me - put me at our california location and I'm in NY. And there's a marker at my location. It did find a marker though!
@mheavers - There's an error in the code. change from(i=1 to from(i=0. It wasn't including the first marker.
@Magico you cannot turn javascript into php code. you can write a php wrapper that generates javascript code like in the answer. If you can't do it on your own, don't use php at all ...
|
79

You can use the computeDistanceBetween() method in the google.maps.geometry.spherical namespace.

Comments

38

I'd like to expand on Leor's suggestion and provide a working solution:

I'm using markers in a markers array e.g. var markers = [];.

Then let's have our position as something like var location = new google.maps.LatLng(51.99, -0.74);

Then we simply reduce our markers against the location we have like so:

markers.reduce(function (prev, curr) { var cpos = google.maps.geometry.spherical.computeDistanceBetween(location.position, curr.position); var ppos = google.maps.geometry.spherical.computeDistanceBetween(location.position, prev.position); return cpos < ppos ? curr : prev; }).position 

What pops out is your closest marker LatLng object.

5 Comments

awesome answer!
Neat & clean answer!
Could this be used to sort the markers by distance, rather then just return one?
Sure @Louis, look up the filter method. You can use that to sort them
I got it working by removing position on the location object; like so: computeDistanceBetween(location, prev.position) ... because location is already a LatLng object.
10

The formula above didn't work for me, but I used this without any issue. Pass your current location to the function, and loop through an array of markers to find the closest:

function find_closest_marker( lat1, lon1 ) { var pi = Math.PI; var R = 6371; //equatorial radius var distances = []; var closest = -1; for( i=0;i<markers.length; i++ ) { var lat2 = markers[i].position.lat(); var lon2 = markers[i].position.lng(); var chLat = lat2-lat1; var chLon = lon2-lon1; var dLat = chLat*(pi/180); var dLon = chLon*(pi/180); var rLat1 = lat1*(pi/180); var rLat2 = lat2*(pi/180); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(rLat1) * Math.cos(rLat2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; distances[i] = d; if ( closest == -1 || d < distances[closest] ) { closest = i; } } // (debug) The closest marker is: console.log(markers[closest]); } 

2 Comments

How do you populate the markers array? Is it by creating a marker using var marker1 = new google.maps.Marker({ ... })?
@enchance I had to do this: map.markers = map.markers || []; then for each marker map.markers.push(marker);
5

Are you aware of Mysql Spatial extensions?

You could use something like MBRContains(g1,g2).

1 Comment

again ^^ both are 404 - problem with link-only answers.
5

Use computeDistanceBetween() Google map API method to calculate near marker between your location and markers list on google map.

Steps:-

  1. Create marker on google map.
    function addMarker(location) { var marker = new google.maps.Marker({ title: 'User added marker', icon: { path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW, scale: 5 }, position: location, map: map }); }

  2. On Mouse click create event for getting lat, long of your location and pass that to find_closest_marker().

    function find_closest_marker(event) { var distances = []; var closest = -1; for (i = 0; i < markers.length; i++) { var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].position, event.latLng); distances[i] = d; if (closest == -1 || d < distances[closest]) { closest = i; } } alert('Closest marker is: ' + markers[closest].getTitle()); } 

visit this link follow the steps. You will able to get nearer marker to your location.

Comments

4

Here is another function that works great for me, returns distance in kilometers:

 function distance(lat1, lng1, lat2, lng2) { var radlat1 = Math.PI * lat1 / 180; var radlat2 = Math.PI * lat2 / 180; var radlon1 = Math.PI * lng1 / 180; var radlon2 = Math.PI * lng2 / 180; var theta = lng1 - lng2; var radtheta = Math.PI * theta / 180; var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta); dist = Math.acos(dist); dist = dist * 180 / Math.PI; dist = dist * 60 * 1.1515; //Get in in kilometers dist = dist * 1.609344; return dist; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.