Google Maps Api v3 - поиск ближайших маркеров

89

Когда я нажимаю на карту, какой способ лучше всего найти ближайший маркер или маркеры? Есть ли в API некоторые функции, которые помогут мне в этом?

это google map api v3.

user198003
источник
1
Используете ли вы какую-либо базу данных для хранения координат маркеров?
Argiropoulos Stavros
Конечно, позиции маркеров хранятся в базе данных mysql.
user198003

Ответы:

113

Сначала вам нужно добавить прослушиватель событий

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

Затем создайте функцию, которая перебирает массив маркеров и использует формулу гаверсинуса для вычисления расстояния каждого маркера от щелчка.

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);
}

Это отслеживает ближайшие маркеры и предупреждает его заголовок.

У меня есть маркеры в виде массива на моем объекте карты

Гален
источник
2
Не для того, чтобы открывать старую ветку, но я попытался реализовать это, и, похоже, он ищет в восточном направлении, а не находит ближайший. Так что, если я ищу место, он будет искать на востоке и найдет ближайший там путь, даже если на западе есть РЕАЛЬНАЯ близость. Имеет ли это смысл?
LeeR
@Lee - это имеет смысл, но я не могу повторить проблему
Гален
1
Да, это вообще не сработало для меня - поместите меня в нашу Калифорнию, а я в Нью-Йорке. И в моем местонахождении есть маркер. Но он нашел маркер!
mheavers
@mheavers - Ошибка в коде. изменить с (i = 1 на from (i = 0. Он не включал первый маркер.
Гален,
1
@Magico нельзя превратить javascript в код php. вы можете написать оболочку php, которая генерирует код javascript, как в ответе. Если вы не можете сделать это самостоятельно, не используйте php вообще ...
Дэниел В.
30

Я хотел бы расширить предложение Леора для всех, кто не понимает, как вычислить ближайшее местоположение и фактически предоставить рабочее решение:

Я использую маркеры в markersмассиве, например var markers = [];.

Тогда давайте представим нашу позицию примерно так: var location = new google.maps.LatLng(51.99, -0.74);

Затем мы просто уменьшаем наши маркеры относительно того места, которое у нас есть:

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

Выскакивает ближайший к вам LatLngобъект- маркер .

Джонатан
источник
1
отличный ответ!
Сезар Алонсо
Аккуратный и чистый ответ!
TheeBen
Можно ли использовать это для сортировки маркеров по расстоянию, а не просто вернуть один?
Louis W
Конечно, @Louis, поищите метод фильтрации. Вы можете использовать это, чтобы отсортировать их
Джонатан
1
Я заставил это работать, удалив позицию на объекте местоположения; вот так: computeDistanceBetween (location, prev.position) ... потому что location уже является объектом LatLng.
holm50
9

Приведенная выше формула не сработала для меня, но я использовал ее без проблем. Передайте свое текущее местоположение функции и переберите в цикле массив маркеров, чтобы найти ближайший:

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]);
}
Mheavers
источник
1
Как вы заполняете markersмассив? Это путем создания маркера с помощью var marker1 = new google.maps.Marker({ ... })?
enchance
1
@enchance я должен был сделать это: map.markers = map.markers || [];затем для каждого маркераmap.markers.push(marker);
Трэвис
4

Вот еще одна функция, которая отлично мне подходит, возвращает расстояние в километрах:

 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;
    }
Крис Панайотофф
источник
3

Используйте метод computeDistanceBetween () API карты Google для вычисления ближайшего маркера между вашим местоположением и списком маркеров на карте Google.

Шаги: -

  1. Создать маркер на карте Google.
    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. Щелкнув мышью, создайте событие для получения широты и долготы вашего местоположения и передайте его в 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());
        }
    

перейдите по этой ссылке, следуйте инструкциям. Вы сможете приблизить маркер к вашему местоположению.

Викеш
источник