97

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.

RedBlueThing
  • 42,006
  • 17
  • 96
  • 122
user198003
  • 11,029
  • 28
  • 94
  • 152

7 Answers7

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

Galen
  • 29,976
  • 9
  • 71
  • 89
  • 3
    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? – LeeR May 23 '11 at 22:35
  • @Lee - it makes sense, but i can't duplicate the issue – Galen May 25 '11 at 21:54
  • 2
    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 Jul 22 '11 at 17:23
  • @mheavers - There's an error in the code. change from(i=1 to from(i=0. It wasn't including the first marker. – Galen Jul 23 '11 at 17:29
  • I don't know enough about navigation or math. Are the distances returned by this function in km? Miles? Some other unit? – Kirkman14 Jul 12 '12 at 15:16
  • How do you populate the map object? I mean what js do I type to get 5 positions on my google map? – enchance Sep 28 '12 at 19:36
  • 1
    @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 ... – Daniel W. Sep 27 '13 at 16:27
  • @Galen are these driving distances or straight line distances? – Web User Jan 11 '16 at 13:14
  • Admittedly, a literal edge case, but does this work if the longitude of the two points are in different hemispheres (ie 179 degrees East and 179 degrees West)? And I presume it doesn't allow for the difference in ground distance between degrees of longitude as you move North and South. Might be better to use the Great Circle calculation – Luke Stevenson Apr 01 '21 at 08:16
79

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

Leor
  • 1,252
  • 11
  • 12
36

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.

Jonathan
  • 10,936
  • 8
  • 64
  • 79
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]);
}
lorem monkey
  • 3,942
  • 3
  • 35
  • 49
mheavers
  • 29,530
  • 58
  • 194
  • 315
  • 1
    How do you populate the `markers` array? Is it by creating a marker using `var marker1 = new google.maps.Marker({ ... })`? – enchance Sep 29 '12 at 13:42
  • 1
    @enchance I had to do this: `map.markers = map.markers || [];` then for each marker `map.markers.push(marker);` – travis Oct 24 '12 at 19:31
5

Are you aware of Mysql Spatial extensions?

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

Argiropoulos Stavros
  • 9,436
  • 11
  • 61
  • 79
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.

vikesh
  • 96
  • 2
  • 9
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;
    }
Chris Panayotoff
  • 1,744
  • 21
  • 24