【问题标题】:Google Maps v3: Enforcing min. zoom level when using fitBoundsGoogle Maps v3:强制执行最低要求。使用 fitBounds 时的缩放级别
【发布时间】:2011-02-28 17:04:44
【问题描述】:

我正在地图上绘制一系列标记(使用地图 API 的 v3)。

在 v2 中,我有以下代码:

  bounds = new GLatLngBounds();

  ... loop thru and put markers on map ...
  bounds.extend(point);
  ... end looping

  map.setCenter(bounds.getCenter());
  var level = map.getBoundsZoomLevel(bounds);
  if ( level == 1 ) 
    level = 5;
  map.setZoom(level > 6 ? 6 : level);

这样可以确保地图上始终显示适当的详细程度。

我正在尝试在 v3 中复制此功能,但 setZoom 和 fitBounds 似乎不合作:

... loop thru and put markers on the map
  var ll = new google.maps.LatLng(p.lat,p.lng);
  bounds.extend(ll);
... end loop

var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);
map.fitBounds(bounds);

我尝试了不同的排列(例如,在 setZoom 之前移动 fitBounds),但我对 setZoom 所做的一切似乎都不会影响地图。我错过了什么吗?有没有办法做到这一点?

【问题讨论】:

    标签: javascript google-maps google-maps-api-3 fitbounds


    【解决方案1】:

    this discussion on Google Groups 我发现基本上当您执行 fitBounds 时,缩放是异步发生的,因此您需要捕获缩放和边界更改事件。最后一篇文章中的代码对我进行了一些小的修改......就目前而言,它可以阻止你完全缩放大于 15,所以使用第四篇文章的想法来设置一个标志,只在第一次这样做。

    // Do other stuff to set up map
    var map = new google.maps.Map(mapElement, myOptions);
    // This is needed to set the zoom after fitbounds, 
    google.maps.event.addListener(map, 'zoom_changed', function() {
        zoomChangeBoundsListener = 
            google.maps.event.addListener(map, 'bounds_changed', function(event) {
                if (this.getZoom() > 15 && this.initialZoom == true) {
                    // Change max/min zoom here
                    this.setZoom(15);
                    this.initialZoom = false;
                }
            google.maps.event.removeListener(zoomChangeBoundsListener);
        });
    });
    map.initialZoom = true;
    map.fitBounds(bounds);
    

    希望对你有帮助,

    安东尼。

    【讨论】:

    • 这是个好方法。另一种方法是检查当前边界并扩展边界,即 stackoverflow.com/questions/3334729/… 。虽然这里的链接答案只是将范围扩大了一个分数,但您可以使用相同的方法将范围扩大一个更大的数字;我发现向所有角添加 7 效果很好。
    • 我想更正我之前的评论。我认为可能需要设置 initialZoom 属性。在省略了那部分代码后,我在 IE 9 上放大时遇到了一些麻烦......很酷的解决方案!
    • 使用google.maps.event.addListenerOnce(),这样以后就不用手动移除监听了。
    • 因为我已经看第三次了,这里是打高尔夫球的版本。谢谢@pstadler。 google.maps.event.addListenerOnce(map, 'bounds_changed', function() { this.setZoom(Math.min(15, this.getZoom())); });
    • 使用 addLIsenerOnce 时,您可以简单地收听 zoom_changed。我在map.fitBounds(bounds); 之前使用zoom_changed,似乎在Chrome 上运行良好。
    【解决方案2】:

    如果不尝试,我会说您应该能够通过在获得缩放级别之前拥有fitBounds() 来做到这一点,即

    map.fitBounds(bounds);
    var zoom = map.getZoom();
    map.setZoom(zoom > 6 ? 6 : zoom);
    

    如果您尝试过但没有成功,您可以在MapOptions 中使用minZoom 设置您的地图(api-reference),如下所示:

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

    这将防止地图在使用fitBounds() 时进一步缩小。

    【讨论】:

    • 不错的简单优雅的解决方案!
    • 设置 minZoom 和 maxZoom 值会限制用户缩放超出这些值,因此如果您只想将初始缩放设置为合理的值(我认为OP在谈论)
    • 所以基本上和我在回答中写的完全一样?
    • @Izazael 提出了一个很好的观点,答案中没有涵盖。这对于阻止fitBounds() 缩放太远非常有用,但它也限制了用户与地图缩放按钮的交互。如果您希望用户拥有完全控制权,那么接受的答案是更好的选择。
    • 可能无法工作,因为有新版本。 fitBounds() 异步工作!
    【解决方案3】:

    Anthony 的解决方案非常好。我只需要修复初始页面加载的缩放(确保您在开始时不会放大太多),这对我有用:

    var zoomChangeBoundsListener =
        google.maps.event.addListener(map, 'bounds_changed', function(event) {
            google.maps.event.removeListener(zoomChangeBoundsListener);
            map.setZoom( Math.min( 15, map.getZoom() ) );
        });
    
    
    map.fitBounds( zoomBounds );
    

    【讨论】:

    • 你可以使用addListenerOnce而不是删除监听器,但我正在使用这个解决方案。
    【解决方案4】:

    就我而言,我只是想将缩放级别设置为比谷歌地图在 fitBounds 期间为我选择的缩放级别小一。目的是使用 fitBounds,但也要确保在任何地图工具等下没有标记。

    我的地图是提前创建的,然后页面的许多其他动态组件有机会添加标记,每次添加后调用 fitBounds。

    这是在最初创建地图对象的初始块中...

    var mapZoom = null;
    

    然后将其添加到添加标记的每个块中,就在调用 map.fitBounds 之前...

    google.maps.event.addListenerOnce(map, 'bounds_changed', function() { 
        if (mapZoom != map.getZoom()) { 
            mapZoom = (map.getZoom() - 1); 
            map.setZoom(mapZoom); 
        } 
    });
    

    在没有检查到位的情况下使用“bounds_changed”时,无论是否需要,地图都会为每个标记缩小一次。相反,当我使用“zoom_changed”时,有时我会在地图工具下有标记,因为缩放实际上并没有改变。现在它总是被触发,但检查确保它只在需要时才缩小一次。

    希望这会有所帮助。

    【讨论】:

    • 这似乎是唯一应该实际使用addListener而不是在每个map.fitBounds()之前重复(并依赖于记住)addListenerOnce的答案
    【解决方案5】:

    当您在一项上调用 map.fitBounds() 时 - 地图可能会放大得太近。要解决此问题,只需将“maxZoom”添加到 mapOptions...

    var mapOptions = {
      maxZoom: 15
    };
    

    【讨论】:

      【解决方案6】:

      由于 Google Maps V3 是事件驱动的,您可以告诉 API 在 zoom_changed 事件触发时将缩放设置回适当的量:

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

      我使用 initial 使地图在最终 fitBounds 被执行时不会缩放太多,而是让用户随心所欲地缩放。如果没有该条件,用户将可以进行任何超过 11 的缩放事件。

      【讨论】:

        【解决方案7】:

        您也可以在调用 fitBounds() 之前设置 maxZoom 选项并在之后重置该值:

        if(!bounds.isEmpty()) {
            var originalMaxZoom = map.maxZoom;
            map.setOptions({maxZoom: 18});
            map.fitBounds(bounds);
            map.setOptions({maxZoom: originalMaxZoom});
        }
        

        【讨论】:

        • 我喜欢这个选项,因为它不会像许多其他选项那样导致 zoom_changed 事件触发两次
        • 当最大对象定义了 maxZoom 选项时很棒的解决方案。
        【解决方案8】:

        我发现以下工作非常好。它是 Ryan 的 answerhttps://stackoverflow.com/questions/3334729/... 的变体。它保证显示的区域至少是offset 值的两倍(以度为单位)。

        const center = bounds.getCenter()
        const offset = 0.01
        const northEast = new google.maps.LatLng(
            center.lat() + offset,
            center.lng() + offset
        )
        const southWest = new google.maps.LatLng(
            center.lat() - offset,
            center.lng() - offset
        )
        const minBounds = new google.maps.LatLngBounds(southWest, northEast)
        map.fitBounds(bounds.union(minBounds))
        

        【讨论】:

          【解决方案9】:

          我只是有同样的任务要解决,并使用了一个简单的函数来解决它。

          它不关心边界中有多少标记 - 如果有很多并且缩放已经很远,这会缩小一点,但是当只有一个标记时(或者非常接近彼此),那么缩小很重要(可使用extendBy 变量自定义):

          var extendBounds = function() {
            // Extends the Bounds so that the Zoom Level on fitBounds() is a bit farer away
            var extendBy = 0.005;
            var point1 = new google.maps.LatLng(
              bounds.getNorthEast().lat() + extendBy,
              bounds.getNorthEast().lng() + extendBy
            )
            var point2 = new google.maps.LatLng(
              bounds.getSouthWest().lat() - extendBy,
              bounds.getSouthWest().lng() - extendBy
            )
            bounds.extend(point1);
            bounds.extend(point2);
          }
          

          要使用它,我使用自己的函数来执行 fitBounds()
          地图是我的 GoogleMap 对象

          var refreshBounds = function() {
            extendBounds();
            map.fitBounds(bounds);
          }
          

          【讨论】:

            猜你喜欢
            • 2015-08-27
            • 2011-04-18
            • 1970-01-01
            • 2013-12-27
            • 2011-08-30
            • 2011-03-16
            • 2011-09-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多