Google Maps V3: показывать маркеры только в окне просмотра - PullRequest
29 голосов
/ 31 мая 2010

Мне нравится создавать карту с помощью Google Maps, которая может обрабатывать большое количество маркеров (более 10.000). Чтобы не замедлять работу карты, я создал XML-файл, который выводит только маркеры, которые находятся внутри текущего видового экрана.

Сначала я использую initialize () для настройки параметров карты:

function initialize() {
    var myLatlng = new google.maps.LatLng(51.25503952021694,3.27392578125);
    var myOptions = {
        zoom: 8,
        center: myLatlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

    google.maps.event.addListener(map, 'tilesloaded', function () {
    loadMapFromCurrentBounds(map);
    }); 
}

Когда событие 'tileloaded' закончено, я использую loadMapFromCurrentBounds (), эта функция получит текущие границы и отправит запрос в XML-файл, чтобы показать маркеры, которые находятся внутри текущего окна просмотра:

function loadMapFromCurrentBounds(map) {

    // First, determine the map bounds
    var bounds = map.getBounds();

    // Then the points
    var swPoint = bounds.getSouthWest();
    var nePoint = bounds.getNorthEast();

    // Now, each individual coordinate
    var swLat = swPoint.lat();
    var swLng = swPoint.lng();
    var neLat = nePoint.lat();
    var neLng = nePoint.lng();

    downloadUrl("mapsxml.php?swLat="+swLat+"&swLng="+swLng+"&neLat="+neLat+"&neLng="+neLng+"", function(data) {
        var xml = parseXml(data);
        var markers = xml.documentElement.getElementsByTagName("marker");
        var infoWindow = new google.maps.InfoWindow; 

        for (var i = 0; i < markers.length; i++) {
            var address = markers[i].getAttribute("address");
            var type = markers[i].getAttribute("type");
            var name = markers[i].getAttribute("name");

            var point = new google.maps.LatLng( 
            parseFloat(markers[i].getAttribute("lat")),
            parseFloat(markers[i].getAttribute("lng"))
            );

            var html = "<b>" + name + "</b> <br/>" + address;
            var icon = customIcons[type] || {};

            var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow});

            bindInfoWindow(marker, map, infoWindow, html);
        }
    })
}

Это прекрасно работает, однако, текущий код не выгружает маркеры, которые больше не находятся в области просмотра. Кроме того, он снова загружает уже загруженные маркеры, что очень быстро замедляет карту при перемещении карты раз в ту же область.

Так что, когда видовой экран изменяется, мне нравится сначала очистить всю карту перед загрузкой новых маркеров. Каков наилучший способ сделать это?

Ответы [ 6 ]

15 голосов
/ 01 июня 2010

Вам нужно добавить еще одного прослушивателя событий на карту:

google.maps.event.addListener(map,'bounds_changed', removeMarkers);

См. здесь , чтобы узнать больше об удалении всех маркеров с карты Google - к сожалению, я не думаю, что это можно сделать одним вызовом. Таким образом, вам нужно написать removeMarkers или что-то подобное, которое должно будет перебирать все маркеры на карте, удаляя их по отдельности, например:

 markersArray[i].setMap(null);

Я не знаю, быстрее ли проверить, находится ли маркер в окне просмотра перед удалением, используя:

 map.getBounds();

Подробнее о событиях Google Map API v3

6 голосов
/ 20 июля 2010

Вы можете проверить эту тему. Даниэль ответил на это довольно мило.

Какой самый эффективный способ создания маршрутов на картах Google из файлов GPS?

Кроме того, bounds_changed - это первая возможность вызвать вашу функцию. плитка загружена, будет вызываться постоянно. Окно просмотра может содержать несколько плиток для заполнения окна просмотра.

Кроме того, вы также можете сделать setVisible (false).

Чтобы убрать маркер, вам может потребоваться удалить слушателей.

google.maps.event.clearInstanceListeners(marker);
marker.setMap(null);
markers.remove(marker);
delete marker;
5 голосов
/ 22 ноября 2013

Из-за нижеследующего объяснения использование «tileloaded» или «bounds_changed» было бы очень неправильным и вызывало нежелательные непрерывные выстрелы. Вместо этого вы захотите использовать событие 'idle', которое будет срабатывать, когда пользователь перестанет панорамировать / масштабировать.

google.maps.event.addListener (map, 'idle', loadMapFromCurrentBounds);

https://developers.google.com/maps/articles/toomanymarkers#viewportmarkermanagement

4 голосов
/ 20 апреля 2012

Эта статья проходит через это довольно красиво: Динамическая загрузка тысяч маркеров в Google Maps

  • динамическая загрузка маркеров до достижения порога
  • сохранить хэш-таблицу маркеров, которые уже были добавлены
  • после достижения порога, удалить маркеры, которых в данный момент нет в области просмотра
  • удалить все маркеры с карты, когда пользователь имеетуменьшите масштаб и не загружайте маркеры, пока пользователь не вернется к разумному уровню
1 голос
/ 24 июля 2012

Ваша оригинальная функция выглядит как много кода. Я бы сделал что-то вроде этого:

if( map.getBounds().contains(markers[i].getPosition()) ) {
   myMarkerDisplayFunction(markers[i]);
}
0 голосов
/ 27 февраля 2013

Вы можете проверить эту документацию в Google . Это объясняет, что вам нужно:

With the new list of markers you can remove the current markers 
(marker.setMap(null)) that are on the map and 
add the new ones (marker.setMap(map)).
...