Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 谷歌地图API V3-在完全相同的位置上有多个标记_Javascript_Google Maps_Google Maps Api 3 - Fatal编程技术网

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

Javascript 谷歌地图API V3-在完全相同的位置上有多个标记,javascript,google-maps,google-maps-api-3,Javascript,Google Maps,Google Maps Api 3,这个有点卡住了。我正在通过JSON检索地理坐标列表,并将它们弹出到谷歌地图上。除了在同一个点上有两个或多个标记的情况外,其他情况都很好。API仅显示1个标记-顶部标记。我想这是很公平的,但我想找到一种方式来展示它们 我搜索过谷歌,找到了一些解决方案,但它们似乎大多是针对API的V2版本,或者只是不太好。理想情况下,我想要一个解决方案,您可以单击某种组标记,然后显示标记聚集在所有标记所在的点周围 任何人都有这个问题或类似的问题,愿意分享解决方案吗?查看V3-此库将附近的点聚集到一个组标记中。单击簇

这个有点卡住了。我正在通过JSON检索地理坐标列表,并将它们弹出到谷歌地图上。除了在同一个点上有两个或多个标记的情况外,其他情况都很好。API仅显示1个标记-顶部标记。我想这是很公平的,但我想找到一种方式来展示它们

我搜索过谷歌,找到了一些解决方案,但它们似乎大多是针对API的V2版本,或者只是不太好。理想情况下,我想要一个解决方案,您可以单击某种组标记,然后显示标记聚集在所有标记所在的点周围


任何人都有这个问题或类似的问题,愿意分享解决方案吗?

查看V3-此库将附近的点聚集到一个组标记中。单击簇时,贴图将放大。我可以想象,放大后,在同一地点的标记仍然存在同样的问题。

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

如果标记位于同一建筑中,则偏移标记不是真正的解决方案。您可能需要修改markerclusterer.js,如下所示:

  • 在MarkerClusterer类中添加一个原型click方法,如下所示-稍后我们将在map initialize()函数中重写此方法:

    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    
    // BEGIN MODIFICATION (around line 715)
    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    // END MODIFICATION
    
  • 在ClusterCon类中,在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);
    }
    
    // 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
    
  • 然后,在initialize()函数中初始化映射并声明MarkerClusterer对象:

    markerCluster = new MarkerClusterer(map, markers);
    // onClickZoom OVERRIDE
    markerCluster.onClickZoom = function() { return multiChoice(markerCluster); }
    
    markerCluster = new MarkerClusterer(map, markers);
    // onClick OVERRIDE
    markerCluster.onClick = function(clickedClusterIcon) { 
      return multiChoice(clickedClusterIcon.cluster_); 
    }
    
    其中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;
    }
    
    function multiChoice(clickedCluster) {
      if (clickedCluster.getMarkers().length > 1)
      {
        // var markers = clickedCluster.getMarkers();
        // do something creative!
        return false;
      }
      return true;
    };
    
    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;
    }
    
    功能多选(mc){
    var cluster=mc.clusters;
    //如果超过1个点共享同一lat/long
    //群集阵列的大小将为1和
    //群集中的标记数将大于1
    //记住:maxZoom已经到达,我们不能再放大了
    if(cluster.length==1&&cluster[0]。标记长度>1)
    {
    var markers=cluster[0]。markers\uux;
    对于(var i=0;i

  • @Ignatius最优秀的答案,已更新为使用MarkerClustererPlus的v2.0.7

      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
    
  • 在MarkerClusterer类中添加一个原型click方法,如下所示-稍后我们将在map initialize()函数中重写此方法:

    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    
    // BEGIN MODIFICATION (around line 715)
    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    // END MODIFICATION
    
  • 在ClusterCon类中,在click/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);
    }
    
    // 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
    
  • 然后,在initialize()函数中初始化映射并声明MarkerClusterer对象:

    markerCluster = new MarkerClusterer(map, markers);
    // onClickZoom OVERRIDE
    markerCluster.onClickZoom = function() { return multiChoice(markerCluster); }
    
    markerCluster = new MarkerClusterer(map, markers);
    // onClick OVERRIDE
    markerCluster.onClick = function(clickedClusterIcon) { 
      return multiChoice(clickedClusterIcon.cluster_); 
    }
    
    其中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;
    }
    
    function multiChoice(clickedCluster) {
      if (clickedCluster.getMarkers().length > 1)
      {
        // var markers = clickedCluster.getMarkers();
        // do something creative!
        return false;
      }
      return true;
    };
    
    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;
    }
    
  • 继续扩展,我实现了一个函数,在给定一个坐标完全相同的位置列表(具有
    lng
    lat
    属性的对象)的情况下,将它们稍微移离原始位置(在适当的位置修改对象)。然后,它们围绕中心点形成一个漂亮的圆

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

    var correctLocList=函数(loclist){
    var lng_半径=0.0003,//经度间隔
    拉图至拉图液化天然气=111.23/71.7,//华沙拉图至拉长比例
    角度=0.5,//起始角度,弧度
    loclen=loclist.length,
    步骤=2*Math.PI/loclen,
    我
    loc,
    横向半径=液化天然气横向半径/横向至横向液化天然气;
    对于(i=0;i
    看一看。
    有一个演示页面,但他们没有显示完全在同一地点的标记,只有一些非常接近

    但在上可以看到一个真实的例子,在同一个点上有标记(向下滚动地图,点击几个标记以查看蜘蛛效果)

    这似乎是解决您问题的最佳方案。

    检查以下内容:

    这是修改后的MarkerCluster,当在同一位置有多个标记时,它在簇标记中有一个信息窗口


    您可以在这里看到它是如何工作的:

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

    已更新以使用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
    
    google.maps.event.trigger(mc,“click”,cClusterIcon.cluster);
    google.maps.event.trigger(mc,“clusterclick”,cClusterIcon.cluster)//弃用名称
    //开始修改
    var zoom=mc.getMap().getZoom();
    //尝试动态拉取此选项会使放大的簇无法渲染
    //那是什么时候让这个没用了-NNC@BNB
    //var maxZoom=mc.getMaxZoom();
    var-maxZoom=15;
    //如果我们已到达maxZoom,并且此群集中有多个标记
    //使用onClick方法弹出选项列表
    if(zoom>=maxZoom&&cClusterIcon.cluster\uu.markers\uu.length>1){
    var marke
    
    //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);
                    } 
                }            
            });