Google Maps V3:仅在视口中显示标记 - 清除标记问题

时间:2010-05-31 12:22:01

标签: javascript google-maps google-maps-api-3 google-maps-markers

我喜欢用谷歌地图创建一个可以处理大量标记的地图(超过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);
    }); 
}

当事件'tilesloaded'完成后,我使用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 个答案:

答案 0 :(得分:15)

您需要向地图添加另一个事件侦听器:

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

有关从Google地图中删除所有标记的详情,请参阅here - 遗憾的是我不认为可以通过一次调用完成。所以你必须编写removeMarkers或类似的东西,它们必须遍历地图上的所有标记,将它们单独删除,如下所示:

 markersArray[i].setMap(null);

我不知道在使用以下方法删除之前检查标记是否在视口中是否更快:

 map.getBounds();

Read more about Google Map API v3 events

答案 1 :(得分:6)

您可能想查看此主题。丹尼尔很好地回答了这个问题。

What's the most efficient way to create routes on google maps from gps files?

另外,bounds_changed是第一次调用你的函数的机会。 tilesloaded,将不断调用。视口可能包含多个图块以填充视口。

或者,您也可以执行setVisible(false)。

要删除标记,您可能需要删除侦听器。

google.maps.event.clearInstanceListeners(marker);
marker.setMap(null);
markers.remove(marker);
delete marker;

答案 2 :(得分:5)

由于使用'tilesloaded'或'bounds_changed'的以下解释将是非常错误的并导致不愿意连续发射。相反,你会想要使用'idle'事件,一旦用户停止平移/缩放就会触发该事件。

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

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

答案 3 :(得分:4)

本文详细介绍了它: Dynamically loading thousands of markers in Google Maps

  
      
  • 动态加载标记,直到达到阈值
  •   
  • 保留已添加的标记的哈希表
  •   
  • 达到阈值后,删除当前不在视口中的标记
  •   
  • 在用户缩小时从地图中删除所有标记,并且在用户缩放到合理级别之前不加载任何标记
  •   

答案 4 :(得分:1)

您的原始功能似乎很多代码。我会做这样的事情:

if( map.getBounds().contains(markers[i].getPosition()) ) {
   myMarkerDisplayFunction(markers[i]);
}

答案 5 :(得分:0)

您可能需要查看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)).