【问题标题】:Google Maps v3 fitBounds() Zoom too close for single markerGoogle Maps v3 fitBounds() 对单个标记来说太近了
【发布时间】:2011-03-21 01:38:46
【问题描述】:

有没有办法为fitBounds() 设置最大缩放级别?我的问题是,当地图只输入一个位置时,它会尽可能放大,这确实使地图脱离上下文并使其无用。也许我采取了错误的方法?

提前致谢!

【问题讨论】:

标签: google-maps fitbounds


【解决方案1】:

我喜欢 mrt 的解决方案(尤其是当您不知道要映射或调整多少点时),除了它会抛出标记,使其不再位于地图的中心。我只是将它扩展了一个额外的点,从 lat 和 lng 中减去 0.01,因此它将标记保持在中心。效果很好,谢谢mrt!

// Pan & Zoom map to show all markers
function fitToMarkers(markers) {

    var bounds = new google.maps.LatLngBounds();

    // Create bounds from markers
    for( var index in markers ) {
        var latlng = markers[index].getPosition();
        bounds.extend(latlng);
    }

    // Don't zoom in too far on only one marker
    if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
       var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
       var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - 0.01, bounds.getNorthEast().lng() - 0.01);
       bounds.extend(extendPoint1);
       bounds.extend(extendPoint2);
    }

    map.fitBounds(bounds);

    // Adjusting zoom here doesn't work :/

}

【讨论】:

  • 保留原始中心的好主意。使用fitBounds() 方法时无法可靠调整缩放级别的原因是因为缩放是异步发生的:stackoverflow.com/questions/2989858/…
  • 这对我很有用。我确实必须将地图引用传递给 V3 上的函数“function fitToMarkers(markers, map)”,但在那之后它就像一个魅力!
  • 喜欢。好一个@ryan。对我来说效果很好,但在我的情况下 .01 缩小得太远了,.001 达到了最佳效果。
  • 谢谢。就像@willdanceforfun 一样,001 恰到好处。
  • 我会推荐这个解决方案stackoverflow.com/questions/2437683/…
【解决方案2】:

您可以像这样在MapOptions (api-reference) 中使用maxZoom 设置您的地图:

var map = new google.maps.Map(document.getElementById("map"), { maxZoom: 10 });

这将防止地图在使用fitBounds() 时放大得更深,甚至会从缩放控件中移除缩放级别。

【讨论】:

  • @candlejack 所以和我的回答中描述的完全一样?
  • 您可以在拟合边界之前设置maxZoom,然后在通过更改边界触发的idle 事件上使用map.setOptions({ maxZoom: undefined }) 再次取消设置。这可以防止放大、缩小效果,而不是在 idle 事件中重置缩放。
【解决方案3】:

另一种解决方案是,如果在执行 fitBounds() 之前检测到边界太小,则扩展边界:

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like
// ...
if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
   var extendPoint = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
   bounds.extend(extendPoint);
}
map.fitBounds(bounds);

【讨论】:

    【解决方案4】:

    添加所有实际边界后,添加这些行

    var offset = 0.002;     
    var center = bounds.getCenter();                            
    bounds.extend(new google.maps.LatLng(center.lat() + offset, center.lng() + offset));
    bounds.extend(new google.maps.LatLng(center.lat() - offset, center.lng() - offset));
    

    它得到真正边界的中心,然后在你中心的东北方向和西南方向添加两个额外的点

    这有效地设置了最小缩放,改变offset的值来增加或减少缩放

    【讨论】:

    • 我不完全理解这是做什么的,但效果很好,谢谢
    【解决方案5】:
    var map = new google.maps.Map(document.getElementById("map"), { maxZoom: 10 });
    

    使用 MaxZoom 选项最适合不缩放以靠近您拥有的标记。

    【讨论】:

    • 太棒了!救生员!
    【解决方案6】:

    如果是针对单个位置,可以使用 setCenter() 和 setZoom() 代替。

    【讨论】:

    • 最简单的解决方案
    【解决方案7】:

    你可以使用

    map.setOptions({
        maxZoom: [what u want],
        minZoom: [what u want]
    });
    

    这样,您可以在地图初始化后设置地图的属性...。您可以根据需要多次设置它们...但在您的情况下...您可以在 fitBounds() 之前设置它们

    祝你好运, 拉鲁图

    【讨论】:

      【解决方案8】:

      我防止地图放大到远处的方法是添加这行代码:

      var zoomOverride = map.getZoom();
              if(zoomOverride > 15) {
              zoomOverride = 15;
              }
            map.setZoom(zoomOverride);
      

      就在这一行之后:

      map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
      

      随意将缩放级别更改为您不希望地图放大过去的任何级别。

      如果您有任何问题或疑问,请在我在 http://icode4you.net/creating-your-own-store-locator-map-how-to-prevent-the-map-from-zooming-in-too-close-on-a-single-marker 写的关于此的博客文章中给我留言

      【讨论】:

      • 我喜欢这个解决方案,但在 if 中插入 setzoom 以不每次都调用它。也可能存在从 getzoom() 返回“未定义”的计时副作用。解决方案:zoom = map.getZoom(); if (typeof zoom !== 'undefined' && zoom > 8) map.setZoom(8);
      【解决方案9】:

      我真的很喜欢 mrt 的解决方案,如果您总是只有一个点可以使用,它会非常有效。但是我确实发现,如果边界框不是基于一个点,而是这些点非常靠近,这仍然可能导致地图放大得太远。

      这是一种首先检查点之间是否在定义的距离内的方法,然后如果它们小于该最小距离,则将边界扩展该最小距离:

      var bounds = new google.maps.LatLngBounds();
      // here you extend your bound as you like
      
      // ...
      
      var minDistance = 0.002;
      var sumA = bounds.getNorthEast().lng() - bounds.getSouthWest().lng();
      var sumB = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();
      
      if((sumA < minDistance && sumA > -minDistance) 
      && (sumB < minDistance && sumB > -minDistance)){
      var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + minDistance, bounds.getNorthEast().lng() + minDistance);
          var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - minDistance, bounds.getNorthEast().lng() - minDistance);
          bounds.extend(extendPoint1);
          bounds.extend(extendPoint2);
      }
      

      希望这对某人有所帮助!

      【讨论】:

        【解决方案10】:

        对于我来说,伙计们,我通过在 fitBounds 之后创建一个空闲事件来解决它。工作完美。猜猜这是这里最干净的解决方案之一

        var locations = [['loc', lat, lng], ['loc', lat, lng]];
        .....
        for (i = 0; i < locations.length; i++) { 
          var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 10
          });
          .... create markers, etc.
        }
        ....
        map.fitBounds(bounds);  
        google.maps.event.addListenerOnce(map, 'idle', function() {
          if (locations.length == 1) {
            map.setZoom(11);
          }
        });
        

        【讨论】:

          【解决方案11】:

          这使您可以直接控制最大允许缩放边界拟合。

          var fitToMarkers = function(map, markers, maxZoom) {
              if (typeof maxZoom == 'undefined') maxZoom = 15;
          
              google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
                  if (this.getZoom() > maxZoom) {
                      this.setZoom(maxZoom);
                  }
              });
          
              var bounds = new google.maps.LatLngBounds();
              for (var m = 0; m < markers.length; m++) {
                  var marker = markers[m];
                  var latlng = marker.getPosition();
                  bounds.extend(latlng);
              }
          
              map.fitBounds(bounds);
          };
          

          【讨论】:

            【解决方案12】:

            我用这个块解决了,因为 Google Maps V3 是事件驱动的:

            zoom_changed 事件触发时,您可以告诉 API 将缩放设置回适当的量:

            var initial = true
            google.maps.event.addListener(map, "zoom_changed", function() {
                if (intial == true){
                   if (map.getZoom() > 11) {
                     map.setZoom(11);
                     intial = false;
                   }
                }
            }); 
            

            我使用 intial 使地图在最终的 fitBounds permorfed 时不会缩放太多加载,如果没有它,任何超过 11 的缩放事件对用户来说都是不可能的。

            【讨论】:

              【解决方案13】:

              调用fitBounds() 方法后,再次尝试设置缩放级别。它将强制地图处于该缩放级别,同时以正确的位置为中心。

              【讨论】:

                【解决方案14】:

                我有基于在拟合边界时限制最大缩放的解决方案。适合我(在 Win 7 - IE 9、FF 13、Chrome 19 上测试):

                // When fitting bounds:
                var bounds = new google.maps.LatLngBounds();
                // ...
                // extend bounds as you like
                // ..
                
                // now set global variable when fitting bounds
                window.fittingBounds = true;
                map.fitBounds(bounds);
                window.fittingBounds = false;
                
                
                // attach this event listener after map init
                google.maps.event.addListener(map, 'zoom_changed', function() {
                    // set max zoom only when fitting bounds
                    if (window.fittingBounds && map.getZoom() > 16) {
                        this.setZoom(16);
                    }
                });
                

                【讨论】:

                  【解决方案15】:

                  还有..这是另一个。
                  与 mrt 和 Ryan 的想法相同,但是

                  • 也适用于边界大小不完全为零 (*)
                  • 防止两极附近变形
                  • 使用 getCenter() 代替 getNorthEast()

                  (*) 注意:如果盒子已经足够大,那么添加这两个额外的点应该没有效果。所以我们不需要任何进一步的检查。

                  function calcBounds(markers) {
                    // bounds that contain all markers
                    var bounds = new google.maps.LatLngBounds();
                    // Using an underscore _.each(). Feel free to replace with standard for()
                    _.each(markers, function(marker) {
                      bounds.extend(marker.getPosition());
                    });
                    // prevent lat/lng distortion at the poles
                    var lng0 = bounds.getNorthEast().lng();
                    var lng1 = bounds.getSouthWest().lng();
                    if (lng0 * lng1 < 0) {
                      // Take the cos at the equator.
                      var cos = 1;
                    }
                    else {
                      var cos0 = Math.cos(lng0);
                      var cos1 = Math.cos(lng1);
                      // Prevent division by zero if the marker is exactly at the pole.
                      var cos_safe = Math.max(cos0, cos1, 0.0001);
                    }
                    var cos0 = Math.cos(bounds.getNorthEast.lng() * Math.PI / 180);
                    var cos1 = Math.cos(bounds.getSouthWest.lng() * Math.PI / 180);
                    // "radius" in either direction.
                    // 0.0006 seems to be an ok value for a typical city.
                    // Feel free to make this value a function argument.
                    var rLat = 0.0006;
                    var rLng = rLat / cos_safe;
                    // expand the bounds to a minimum width and height
                    var center = bounds.getCenter();
                    var p0 = new google.maps.LatLng(center.lat() - rLat, center.lng() - rLng);
                    var p1 = new google.maps.LatLng(lat.center() + rLat, center.lng() + rLng);
                    bounds.extend(p0);
                    bounds.extend(p1);
                    return bounds;
                  }
                  

                  编辑:考虑到我们有墨卡托投影,我不确定我的比率计算是否正确。我可能会重新编辑这个..

                  【讨论】:

                    【解决方案16】:

                    它已经在这里回答了Google Maps v3: Enforcing min. zoom level when using fitBounds 它按预期工作:) 所以现在如果在 fit bounds zoom 小于然后让我们说 13 那么你可以设置你喜欢的新缩放

                    【讨论】:

                      【解决方案17】:

                      这是我的解决方案,当两个标记非常接近时也可以使用。在这两种情况下,有效的最大缩放级别相同。因此,当有多个标记时,我们最终不会不必要地缩小

                      同样的效果是确保最大缩放,而不使用 maxZoom 选项,这可能会导致用户无法使用缩放控件放大到超过 maxZoom 级别

                      我已经预先计算了maxLat、minLat、maxLng和minLng...

                      var minLatSpan = 0.002;
                      if (maxLat - minLat < minLatSpan) {
                        // ensures that we do not zoom in too much
                        var delta = (minLatSpan - (maxLat - minLat)) / 2;
                        maxLat += delta;
                        minLat -= delta;
                      }
                      
                      map.fitBounds({
                        east: maxLng,
                        west: minLng,
                        north: maxLat,
                        south: minLat,
                      });
                      

                      【讨论】:

                        猜你喜欢
                        • 2013-02-24
                        • 2012-07-01
                        • 2018-04-20
                        • 2011-05-02
                        • 2015-08-27
                        • 1970-01-01
                        • 2014-01-05
                        • 2013-02-23
                        相关资源
                        最近更新 更多