我喜欢用谷歌地图创建一个可以处理大量标记的地图(超过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);
}
})
}
这很有效,但是,当前代码不会卸载不再出现在视口中的标记。除此之外,它再次加载已经加载的标记,当在同一区域中移动地图时,它会非常快地减慢地图的速度。
因此,当视口发生变化时,我希望在加载新标记之前先清除整个地图。这样做的最佳方式是什么?
答案 0 :(得分:15)
您需要向地图添加另一个事件侦听器:
google.maps.event.addListener(map,'bounds_changed', removeMarkers);
有关从Google地图中删除所有标记的详情,请参阅here - 遗憾的是我不认为可以通过一次调用完成。所以你必须编写removeMarkers或类似的东西,它们必须遍历地图上的所有标记,将它们单独删除,如下所示:
markersArray[i].setMap(null);
我不知道在使用以下方法删除之前检查标记是否在视口中是否更快:
map.getBounds();
答案 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)).