有点卡在这个上。我正在通过 JSON 检索地理坐标列表并将它们弹出到谷歌地图上。除了在完全相同的位置有两个或更多标记的情况外,一切都运行良好。API 仅显示 1 个标记 - 最上面的标记。我想这很公平,但想找到一种方法来以某种方式显示它们。
我在谷歌上搜索并找到了一些解决方案,但它们似乎大多适用于 API 的 V2 或者不是那么好。理想情况下,我想要一个解决方案,您可以单击某种组标记,然后显示聚集在它们所在位置周围的标记。
任何人都有这个问题或类似的问题,并愿意分享解决方案?
有点卡在这个上。我正在通过 JSON 检索地理坐标列表并将它们弹出到谷歌地图上。除了在完全相同的位置有两个或更多标记的情况外,一切都运行良好。API 仅显示 1 个标记 - 最上面的标记。我想这很公平,但想找到一种方法来以某种方式显示它们。
我在谷歌上搜索并找到了一些解决方案,但它们似乎大多适用于 API 的 V2 或者不是那么好。理想情况下,我想要一个解决方案,您可以单击某种组标记,然后显示聚集在它们所在位置周围的标记。
任何人都有这个问题或类似的问题,并愿意分享解决方案?
看看OverlappingMarkerSpiderfier。
有一个演示页面,但它们没有显示完全在同一位置的标记,只有一些非常靠近。
但是在http://www.ejw.de/ejw-vor-ort/上可以看到一个真实的例子,在完全相同的地方有标记(向下滚动地图并点击几个标记以查看蜘蛛效果)。
这似乎是您问题的完美解决方案。
如果标记位于同一建筑物中,则偏移标记并不是真正的解决方案。您可能想要做的是像这样修改markerclusterer.js:
在 MarkerClusterer 类中添加一个原型 click 方法,就像这样 - 我们稍后将在 map initialize() 函数中覆盖它:
MarkerClusterer.prototype.onClick = function() {
return true;
};
在 ClusterIcon 类中,在 clusterclick 触发器之后添加以下代码:
// Trigger the clusterclick event.
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
var zoom = this.map_.getZoom();
var maxZoom = markerClusterer.getMaxZoom();
// if we have reached the maxZoom and there is more than 1 marker in this cluster
// use our onClick method to popup a list of options
if (zoom >= maxZoom && this.cluster_.markers_.length > 1) {
return markerClusterer.onClickZoom(this);
}
然后,在您初始化地图并声明您的 MarkerClusterer 对象的 initialize() 函数中:
markerCluster = new MarkerClusterer(map, markers);
// onClickZoom OVERRIDE
markerCluster.onClickZoom = function() { return multiChoice(markerCluster); }
multiChoice() 是您的(尚未编写)函数,用于弹出一个带有可供选择的选项列表的信息窗口。请注意,markerClusterer 对象会传递给您的函数,因为您将需要它来确定该集群中有多少个标记。例如:
function multiChoice(mc) {
var cluster = mc.clusters_;
// if more than 1 point shares the same lat/long
// the size of the cluster array will be 1 AND
// the number of markers in the cluster will be > 1
// REMEMBER: maxZoom was already reached and we can't zoom in anymore
if (cluster.length == 1 && cluster[0].markers_.length > 1)
{
var markers = cluster[0].markers_;
for (var i=0; i < markers.length; i++)
{
// you'll probably want to generate your list of options here...
}
return false;
}
return true;
}
我将它与 jQuery 一起使用,它完成了这项工作:
var map;
var markers = [];
var infoWindow;
function initialize() {
var center = new google.maps.LatLng(-29.6833300, 152.9333300);
var mapOptions = {
zoom: 5,
center: center,
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
$.getJSON('jsonbackend.php', function(data) {
infoWindow = new google.maps.InfoWindow();
$.each(data, function(key, val) {
if(val['LATITUDE']!='' && val['LONGITUDE']!='')
{
// Set the coordonates of the new point
var latLng = new google.maps.LatLng(val['LATITUDE'],val['LONGITUDE']);
//Check Markers array for duplicate position and offset a little
if(markers.length != 0) {
for (i=0; i < markers.length; i++) {
var existingMarker = markers[i];
var pos = existingMarker.getPosition();
if (latLng.equals(pos)) {
var a = 360.0 / markers.length;
var newLat = pos.lat() + -.00004 * Math.cos((+a*i) / 180 * Math.PI); //x
var newLng = pos.lng() + -.00004 * Math.sin((+a*i) / 180 * Math.PI); //Y
var latLng = new google.maps.LatLng(newLat,newLng);
}
}
}
// Initialize the new marker
var marker = new google.maps.Marker({map: map, position: latLng, title: val['TITLE']});
// The HTML that is shown in the window of each item (when the icon it's clicked)
var html = "<div id='iwcontent'><h3>"+val['TITLE']+"</h3>"+
"<strong>Address: </strong>"+val['ADDRESS']+", "+val['SUBURB']+", "+val['STATE']+", "+val['POSTCODE']+"<br>"+
"</div>";
// Binds the infoWindow to the point
bindInfoWindow(marker, map, infoWindow, html);
// Add the marker to the array
markers.push(marker);
}
});
// Make a cluster with the markers from the array
var markerCluster = new MarkerClusterer(map, markers, { zoomOnClick: true, maxZoom: 15, gridSize: 20 });
});
}
function markerOpen(markerid) {
map.setZoom(22);
map.panTo(markers[markerid].getPosition());
google.maps.event.trigger(markers[markerid],'click');
switchView('map');
}
google.maps.event.addDomListener(window, 'load', initialize);
扩展Chaoley 的答案,我实现了一个函数,在给定坐标完全相同的位置列表(具有lng
和lat
属性的对象)的情况下,将它们从原始位置移开一点(修改对象到位)。然后它们围绕中心点形成一个漂亮的圆圈。
我发现,对于我的纬度(北纬 52 度),0.0003 度的圆半径效果最好,并且当转换为公里时,您必须弥补纬度和经度之间的差异。您可以在此处找到您所在纬度的近似换算。
var correctLocList = function (loclist) {
var lng_radius = 0.0003, // degrees of longitude separation
lat_to_lng = 111.23 / 71.7, // lat to long proportion in Warsaw
angle = 0.5, // starting angle, in radians
loclen = loclist.length,
step = 2 * Math.PI / loclen,
i,
loc,
lat_radius = lng_radius / lat_to_lng;
for (i = 0; i < loclen; ++i) {
loc = loclist[i];
loc.lng = loc.lng + (Math.cos(angle) * lng_radius);
loc.lat = loc.lat + (Math.sin(angle) * lat_radius);
angle += step;
}
};
@Ignatius 最优秀的答案,已更新以与 MarkerClustererPlus 的 v2.0.7 一起使用。
在 MarkerClusterer 类中添加一个原型 click 方法,就像这样 - 我们稍后将在 map initialize() 函数中覆盖它:
// BEGIN MODIFICATION (around line 715)
MarkerClusterer.prototype.onClick = function() {
return true;
};
// END MODIFICATION
在 ClusterIcon 类中,在 click/clusterclick 触发器之后添加以下代码:
// EXISTING CODE (around line 143)
google.maps.event.trigger(mc, "click", cClusterIcon.cluster_);
google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name
// BEGIN MODIFICATION
var zoom = mc.getMap().getZoom();
// Trying to pull this dynamically made the more zoomed in clusters not render
// when then kind of made this useless. -NNC @ BNB
// var maxZoom = mc.getMaxZoom();
var maxZoom = 15;
// if we have reached the maxZoom and there is more than 1 marker in this cluster
// use our onClick method to popup a list of options
if (zoom >= maxZoom && cClusterIcon.cluster_.markers_.length > 1) {
return mc.onClick(cClusterIcon);
}
// END MODIFICATION
然后,在您初始化地图并声明您的 MarkerClusterer 对象的 initialize() 函数中:
markerCluster = new MarkerClusterer(map, markers);
// onClick OVERRIDE
markerCluster.onClick = function(clickedClusterIcon) {
return multiChoice(clickedClusterIcon.cluster_);
}
multiChoice() 是您的(尚未编写)函数,用于弹出一个带有可供选择的选项列表的信息窗口。请注意,markerClusterer 对象会传递给您的函数,因为您将需要它来确定该集群中有多少个标记。例如:
function multiChoice(clickedCluster) {
if (clickedCluster.getMarkers().length > 1)
{
// var markers = clickedCluster.getMarkers();
// do something creative!
return false;
}
return true;
};