谷歌地图 API V3 - 完全相同的位置上的多个标记

Posted

技术标签:

【中文标题】谷歌地图 API V3 - 完全相同的位置上的多个标记【英文标题】:Google maps API V3 - multiple markers on exact same spot 【发布时间】:2011-04-02 17:05:00 【问题描述】:

有点卡在这个上。我正在通过 JSON 检索地理坐标列表并将它们弹出到谷歌地图上。除了在完全相同的位置上有两个或多个标记的情况外,一切都运行良好。 API 仅显示 1 个标记 - 顶部的标记。我想这很公平,但我想找到一种方法以某种方式显示它们。

我搜索了谷歌并找到了一些解决方案,但它们似乎大多适用于 API 的 V2,或者不是那么好。理想情况下,我想要一个解决方案,您可以单击某种组标记,然后将标记聚集在它们所在的位置周围。

有人遇到过这个问题或类似问题并愿意分享解决方案吗?

【问题讨论】:

【参考方案1】:

我使用了这个http://leaflet.github.io/Leaflet.markercluster/,非常适合我。添加了完整的解决方案。

<html lang="en">
  <head>
    <script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.0.4/leaflet.markercluster.js"></script>
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css" />
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.0.4/MarkerCluster.Default.css" />
 </head>
<body>
   <div id="map"></div>

    <script>
        var addressData = [
            id: 9, name: "Ankita", title: "Manager", latitude: "33.1128019", longitude: "-96.6958939",
            id: 1, name: "Aarti", title: "CEO", latitude: "33.1128019", longitude: "-96.6958939",
            id: 2, name: "Payal", title: "Employee", latitude: "33.0460488", longitude: "-96.9983386"];

        var addressPoints = [];
        for (i = 0; i < addressData.length; i++) 
            var marker = 
                latitude: addressData[i].latitude,
                longitude: addressData[i].longitude,
                coverage: addressData[i]
            ;
            addressPoints.push(marker);
        
        var map = L.map('map').setView(["32.9602172", "-96.7036844"], 5);
        var basemap = L.tileLayer('http://s.basemaps.cartocdn.com/light_all/z/x/y.png', attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>', subdomains: 'abcd');
        basemap.addTo(map);
        
        var markers = L.markerClusterGroup();
        for (var i = 0; i < addressPoints.length; i++) 
           // var icon1 = "app/common_assest/images/pin/redPin.png"; // set ehere you own marker pin whatever you want to set
            var currentMarker = addressPoints[i];
            console.log(currentMarker);
            var contentString = '<div class="mapinfoWindowContent">' +
                    '<div class="mapInfoTitle">Name: ' + currentMarker.coverage.name + '</div>' +
                    '<div class="mapInfoSubText">Licence: ' + currentMarker.coverage.title + '</div>' +
                    '</div>';
   // var myIcon = L.icon(// set ehere you own marker pin whatever you want to set
     // iconUrl: icon1,
    //  iconRetinaUrl: icon1,
   //                );
            var marker = L.marker(new L.LatLng(currentMarker['latitude'], currentMarker['longitude']), 
                title: currentMarker.coverage.name
            );
            marker.bindPopup(contentString);
            markers.addLayer(marker);
        
        markers.addTo(map);
    </script>
</body>

希望它对您有帮助。

【讨论】:

【参考方案2】:

我使用了markerclustererplus,对我来说这是可行的:

//Code
google.maps.event.addListener(cMarkerClusterer, "clusterclick", function (c) 
            var markers = c.getMarkers();
            
            //Check Markers array for duplicate position and offset a little
            if (markers .length > 1) 
                //Check if all markers are in the same position (with 4 significant digits)
                if (markers .every((val, index, arr) => (val.getPosition().lat().toFixed(4) == arr[0].getPosition().lat().toFixed(4)) && (val.getPosition().lng().toFixed(4) == arr[0].getPosition().lng().toFixed(4))))  /
                    //Don't modify first element
                    for (i = 1; i < markers.length; i++) 
                        var existingMarker = markers[i];
                        var pos = existingMarker.getPosition();                        
                        var quot = 360.0 / markers.length;
                        var newLat = pos.lat() + -.00008 * Math.cos(+quot * i); //+ -.00008 * Math.cos((+quot * i) / 180 * Math.PI);  //x                        
                        var newLng = pos.lng() + -.00008 * Math.sin(+quot * i);  //+ -.0008 * Math.sin((+quot * i) / 180 * Math.PI);  //Y
                        existingMarker.setPosition(new google.maps.LatLng(newLat, newLng));                        
                    
                    let cZoom = map.getZoom();
                    map.setZoom(cZoom-1);
                    map.setZoom(cZoom+1);
                 
                        
        );

【讨论】:

【参考方案3】:

添加到上述答案,但在 php 和 wordpress 中提供了另一种快速解决方案。在本例中,我通过 ACF 存储位置字段并循环访问帖子以获取该数据。

我发现将 lat / lng 存储在一个数组中并检查该数组的值以查看循环是否匹配,然后我们可以使用我们想要移动点的数量更新该数组中的值。

//This is the value to shift the pips by. I found this worked best with markerClusterer
$add_to_latlng = 0.00003;

while ($query->have_posts()) 
    $query->the_post();
    $meta = get_post_meta(get_the_ID(), "postcode", true); //uses an acf field to store location
    $lat = $meta["lat"];
    $lng = $meta["lng"];

    if(in_array($meta["lat"],$lat_checker)) //check if this meta matches
        
        //if matches then update the array to a new value (current value + shift value)
        // This is using the lng value for a horizontal line of pips, use lat for vertical, or both for a diagonal
        if(isset($latlng_storer[$meta["lng"]]))
            $latlng_storer[$meta["lng"]] = $latlng_storer[$meta["lng"]] + $add_to_latlng;
            $lng = $latlng_storer[$meta["lng"]];
         else 
            $latlng_storer[$meta["lng"]] = $meta["lng"];
            $lng = $latlng_storer[$meta["lng"]];
        

     else 
        $lat_checker[] = $meta["lat"]; //just for simple checking of data
        $latlng_storer[$meta["lat"]] = floatval($meta["lat"]);
        $latlng_storer[$meta["lng"]] =  floatval($meta["lng"]);
    

    $entry[] = [
        "lat" => $lat,
        "lng" => $lng,
    //...Add all the other post data here and use this array for the pips
    ];
 // end query

一旦我抓取了这些位置,我就会对 $entry 变量进行 json 编码并在我的 JS 中使用它。

let locations = <?=json_encode($entry)?>;

我知道这是一个相当具体的情况,但我希望这对其他人有所帮助!

【讨论】:

【参考方案4】:

添加到 Matthew Fox 鬼鬼祟祟的天才答案中,我在设置标记对象时为每个 lat 和 lng 添加了一个小的随机偏移量。例如:

new LatLng(getLat()+getMarkerOffset(), getLng()+getMarkerOffset()),

private static double getMarkerOffset()
    //add tiny random offset to keep markers from dropping on top of themselves
    double offset =Math.random()/4000;
    boolean isEven = ((int)(offset *400000)) %2 ==0;
    if (isEven) return  offset;
    else        return -offset;

【讨论】:

【参考方案5】:

如何摆脱它.. [斯威夫特]

    var clusterArray = [String]()
    var pinOffSet : Double = 0
    var pinLat = yourLat
    var pinLong = yourLong
    var location = pinLat + pinLong

即将创建一个新标记?检查clusterArray 并操作它的偏移量

 if(!clusterArray.contains(location))
        clusterArray.append(location)
     else 

        pinOffSet += 1
        let offWithIt = 0.00025 // reasonable offset with zoomLvl(14-16)
        switch pinOffSet 
        case 1 : pinLong = pinLong + offWithIt ; pinLat = pinLat + offWithIt
        case 2 : pinLong = pinLong + offWithIt ; pinLat = pinLat - offWithIt
        case 3 : pinLong = pinLong - offWithIt ; pinLat = pinLat - offWithIt
        case 4 : pinLong = pinLong - offWithIt ; pinLat = pinLat + offWithIt
        default : print(1)
        


    

结果

【讨论】:

【参考方案6】:

这更像是一种权宜之计的“快速而肮脏”的解决方案,类似于 Matthew Fox 建议的解决方案,这次使用的是 javascript

在 JavaScript 中,您可以通过向两个位置添加一个小的随机偏移量来偏移所有位置的纬度和经度例如

myLocation[i].Latitude+ = (Math.random() / 25000)

(我发现除以 25000 可以提供足够的分离度,但不会将标记从确切位置(例如特定地址)显着移动)

这样可以很好地将它们相互抵消,但前提是您必须仔细放大。缩小时,仍不清楚该位置是否有多个选项。

【讨论】:

我喜欢这个。如果您不需要准确代表性的标记,只需将 25000 降低到 250 或 25。简单快速的解决方案。 只是一点点改进 - 添加这个以使偏差对称myLocation[i].Latitude- = 1/50000【参考方案7】:

看看OverlappingMarkerSpiderfier。 有一个演示页面,但它们没有显示完全相同的标记,只有一些非常靠近的标记。

但是,在http://www.ejw.de/ejw-vor-ort/ 上可以看到一个在完全相同的位置带有标记的真实示例(向下滚动查看地图并单击几个标记以查看蜘蛛效果)。

这似乎是您问题的完美解决方案。

【讨论】:

这太棒了,并且完美地满足了集群库的需求,它不能处理具有相同纬度/经度的标记。 如果将OverlappingMarkerSpiderfier 与MarkerClusterer 结合使用,一个好的选择是在集群构造函数上设置maxZoom 选项。这会将指定缩放级别后的标记“分群”。 @Tad 我不知道你是不是那个网站的开发者,但我想让你知道 ejw.de 上的地图坏了。我收到一个 JS 错误。 我检查了提议的演示,但它似乎死了。经过进一步研究,我发现了这个关于如何集成标记集群和 Spiderifier 的示例。没有现场演示,只需克隆并按照自述文件进行操作。 github.com/yagoferrer/markerclusterer-plus-spiderfier-example OverlappingMarkerSpiderfier 代码稍旧且死机,并且在问题跟踪器中存在许多未解决的问题。它工作正常,但似乎有很多错误(其中一些对我来说很重要),所以在投入时间之前要小心。【参考方案8】:

我喜欢简单的解决方案,所以这是我的。 而不是修改库,这将使其更难维护。您可以像这样简单地观看活动

google.maps.event.addListener(mc, "clusterclick", onClusterClick);

然后你就可以管理它了

function onClusterClick(cluster)
    var ms = cluster.getMarkers();

i,即使用引导程序显示带有列表的面板。我发现这比在“拥挤”的地方做蜘蛛更舒适和有用。 (如果您使用的是clusterer,那么一旦您进行spiderfy,您最终会发生碰撞)。 你也可以在那里查看缩放。

顺便说一句。我刚刚找到了传单,它似乎工作得更好,集群和 spiderfy 工作得非常流畅http://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.10000.html 而且它是开源的。

【讨论】:

如何获取上述链接的完整示例? @AnkitaDobariya 我不明白你到底在问什么,但如果你转到链接的根目录,你会得到更多信息。否则您可以检查页面,或转到 git 中的代码。 leaflet.github.io/Leaflet.markercluster 好的,对我很有用【参考方案9】:

上面的答案更优雅,但我发现了一种快速而肮脏的方法,实际上效果非常好。您可以在 www.buildinglit.com 看到它的实际应用

我所做的只是在我的 genxml.php 页面的纬度和经度上添加一个随机偏移量,因此每次使用标记创建地图时,它每次返回的结果都略有不同。这听起来像是一个 hack,但实际上您只需要标记在随机方向上轻微移动,如果它们重叠,它们就可以在地图上点击。它实际上工作得很好,我会说比蜘蛛方法更好,因为谁想要处理这种复杂性并让它们无处不在。您只想能够选择标记。随机轻推它效果很好。

这是我的 php_genxml.php 中 while 语句迭代节点创建的示例

while ($row = @mysql_fetch_assoc($result)) $offset = rand(0,1000)/10000000;
$offset2 = rand(0, 1000)/10000000;
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat'] + $offset);
$newnode->setAttribute("lng", $row['lng'] + $offset2);
$newnode->setAttribute("distance", $row['distance']);
$newnode->setAttribute("type", $row['type']);
$newnode->setAttribute("date", $row['date']);
$newnode->setAttribute("service", $row['service']);
$newnode->setAttribute("cost", $row['cost']);
$newnode->setAttribute("company", $company);

注意在 lat 和 long 下有 +offset。从上面的2个变量。我必须将随机数除以 0,1000 除以 10000000,才能得到一个随机小到足以勉强移动标记的小数。随意修改该变量以获得更精确的变量以满足您的需求。

【讨论】:

酷!这是我发现非常有用的脏 hack,不需要弄乱 Google Maps api 代码【参考方案10】:

当用户放大到最大时,给予偏移将使标记远离。所以我找到了实现这一目标的方法。这可能不是正确的方法,但效果很好。

// This code is in swift
for loop markers

//create marker
let mapMarker = GMSMarker()
mapMarker.groundAnchor = CGPosition(0.5, 0.5)
mapMarker.position = //set the CLLocation
//instead of setting marker.icon set the iconView
let image:UIIMage = UIIMage:init(named:"filename")
let imageView:UIImageView = UIImageView.init(frame:rect(0,0, ((image.width/2 * markerIndex) + image.width), image.height))
imageView.contentMode = .Right
imageView.image = image
mapMarker.iconView = imageView
mapMarker.map = mapView

设置标记的 zIndex 以便您可以在顶部看到您想要看到的标记图标,否则它将像自动交换一样为标记设置动画。当用户点击标记时,处理 zIndex 以使用 zIndex Swap 将标记置于顶部。

【讨论】:

【参考方案11】:

扩展上面的答案,当您加入字符串时,而不是添加/减去位置(例如“37.12340-0.00069”),将您的原始纬度/经度转换为浮点数,例如使用 parseFloat(),然后添加或减去更正。

【讨论】:

【参考方案12】:

我将它与 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);

【讨论】:

Thx 非常适合我 :) 正是我从几个小时以来一直在搜索的内容:p 美丽优雅的解决方案。谢谢! 完美的解决方案抵消了一点!有可能吗,我们将鼠标悬停在标记上,然后显示多个标记【参考方案13】:

更新为与 MarkerClustererPlus 一起使用。

  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) 
    var markers = cClusterIcon.cluster_.markers_;
    var a = 360.0 / markers.length;
    for (var i=0; i < markers.length; i++)
    
        var pos = markers[i].getPosition();
        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 finalLatLng = new google.maps.LatLng(newLat,newLng);
        markers[i].setPosition(finalLatLng);
        markers[i].setMap(cClusterIcon.cluster_.map_);
    
    cClusterIcon.hide();
    return ;
  
  // END MODIFICATION

【讨论】:

这种方法需要用户单击集群图标,并且不会涵盖使用缩放滑块或鼠标滚动完成导航的用例。任何想法如何解决这些问题?【参考方案14】:

扩展上面给出的答案,只需确保在初始化地图对象时设置 maxZoom 选项。

【讨论】:

【参考方案15】:

检查这个:https://github.com/plank/MarkerClusterer

当您在同一位置有多个标记时,这是修改后的 MarkerCluster 在群集标记中有一个 infoWindow。

你可以在这里看到它是如何工作的:http://culturedays.ca/en/2013-activities

【讨论】:

【参考方案16】:

如果标记位于同一建筑物中,则偏移标记并不是真正的解决方案。您可能想要做的是像这样修改markerclusterer.js:

    在 MarkerClusterer 类中添加一个原型点击方法,就像这样 - 我们稍后将在 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() 是您的(尚未编写的)函数,用于弹出一个 InfoWindow,其中包含可供选择的选项列表。请注意,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;
    
    

【讨论】:

【参考方案17】:

扩展Chaoley's answer,我实现了一个函数,给定坐标完全相同的位置列表(具有lnglat 属性的对象),将它们从原始位置移开一点点(就地修改对象)。然后它们围绕中心点形成一个漂亮的圆圈。

我发现,对于我的纬度(北 52 度),0.0003 度的圆半径效果最好,并且当转换为公里时,您必须弥补纬度和经度之间的差异。你可以找到你所在纬度的近似转换here。

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

【讨论】:

DzinX,我花了 4 个小时试图弄清楚如何将您的代码实现到我的代码中,但无济于事。我得出的结论是,我对此很烂,非常感谢您的帮助。这是我试图插入代码的地方:pastebin.com/5qYbvybm - 任何帮助将不胜感激!谢谢! WebMW:从 XML 中提取标记后,您必须首先将它们分组到列表中,以便每个列表都包含指向完全相同位置的标记。然后,在每个包含多个元素的列表上,运行correctLocList()。只有在你这样做之后,才能创建 google.maps.Marker 对象。 它不起作用....它只是将我的经纬度从37.68625400000000000,-75.71669800000000000 更改为37.686254,-75.716698 也适用于所有值... M 期待类似... 37.68625400000000000,-75.7166980000000000037.6862540000001234,-75.716698000000123437.6862540000005678,-75.7166980000005678..etc.. 我也试着改变我的角度。 嗯,让我们挖掘一下,希望@DzinX 还在该地区。您能否交配(或其他任何人)解释您如何获得所有这些数字? Lng_radius 等?多谢。 :) @Vae:半径是您希望圆的大小。您希望圆圈以像素为单位,因此您需要知道在您所在的位置,1 度纬度与 1 度经度的比例(以地图上的像素为单位)。你可以在一些网站上找到这个,或者只是试验,直到你得到正确的数字。角度是第一个销从顶部向右的距离。【参考方案18】:

@Ignatius 最出色的答案,已更新为与 MarkerClustererPlus 的 v2.0.7 一起使用。

    在 MarkerClusterer 类中添加一个原型点击方法,就像这样 - 我们稍后将在 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() 是您的(尚未编写的)函数,用于弹出一个 InfoWindow,其中包含可供选择的选项列表。请注意,markerClusterer 对象被传递给您的函数,因为您将需要它来确定该集群中有多少标记。例如:

    function multiChoice(clickedCluster) 
      if (clickedCluster.getMarkers().length > 1)
      
        // var markers = clickedCluster.getMarkers();
        // do something creative!
        return false;
      
      return true;
    ;
    

【讨论】:

谢谢,这完美!至于你的maxZoom 问题,我认为这只是一个问题,如果没有设置 maxZoom 或者集群的 maxZoom 大于地图的缩放。我已经用这个 sn-p 替换了你的硬编码,它似乎工作得很好:var maxZoom = mc.getMaxZoom(); if (null === maxZoom || maxZoom &gt; mc.getMap().maxZoom) maxZoom = mc.getMap().maxZoom; if (null === maxZoom) maxZoom = 15; 我知道这真的很旧,但我正在尝试使用这个解决方案。我有它的工作,但在显示集群数据的信息窗口的情况下......我如何获得首先单击的集群的标记位置,以便我可以显示信息窗口?标记是我的数据数组...但是如何在群集图标/标记上显示信息窗口? @user756659 在 multiChoice 中,您可以通过:clickedCluster.center_.lat() / clickedCluster.center_.lng() 获得 lat/lng @Pascal 并稍加混淆,我们最终得到了这个,它可以工作,但正如 python 的 tao 所说。 “可读性很重要”。 var maxZoom = Math.min(mc.getMaxZoom() || 15, mc.getMap().maxZoom || 15); 嗨@nathancolgate 你能帮忙并建议我更新最新版本。我知道这篇文章已经很老了,但我完全被困住了,正在寻找出路来在同一地点/建筑物上显示多个标记。这将非常有帮助。提前致谢【参考方案19】:

对于同一建筑物中存在多个服务的情况,您可以在距离实际点的半径范围内稍微偏移标记(例如 0.001 度)。这也应该会产生很好的视觉效果。

【讨论】:

【参考方案20】:

查看Marker Clusterer 的 V3 - 这个库将附近的点聚集成一个组标记。单击集群时地图会放大。我想当你放大到同一个位置时,你仍然会遇到同样的问题。

【讨论】:

是的,看看那个方便的小库,但它似乎仍然没有解决问题。我正在为一家公司制作服务定位器,该公司有时在同一个办公大楼内拥有多个服务,因此地理坐标完全相同。我可以在一个信息窗口中显示不同的服务,但这似乎不是最优雅的解决方案...... @Louzoid Marker Clusterer 并没有解决我刚刚发现的问题。我遇到了同样的问题,我在一栋大楼内有几家公司,因此它只显示 1 个标记。

以上是关于谷歌地图 API V3 - 完全相同的位置上的多个标记的主要内容,如果未能解决你的问题,请参考以下文章

地图上的 Google Map Api v3 拖动事件

谷歌地图 API V3 fitBounds() 不工作

如何使用谷歌地图 api v3 旋转地图方向

从谷歌地图 API 的 v2 升级到 v3,建议

使用 Google Maps JavaScript API v3 和 Geocoding API 映射多个位置

如何在谷歌地图 api V3 中偏移中心点