【问题标题】:Get bounds of a google map v3 after zoom change缩放更改后获取谷歌地图 v3 的边界
【发布时间】:2010-11-03 10:27:09
【问题描述】:

我正在尝试在缩放更改后获取地图的边界, 但是 zoom_changed 事件在重新计算边界之前触发。因此,在 zoom_changed 处理程序中,您会得到以前的边界,而不是新的边界。

有什么方法可以让缩放变化得到正确的界限吗?

【问题讨论】:

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


    【解决方案1】:

    我也有同样的问题。这是我最终解决的几个问题,我在其他解决方案中遇到的问题。

    *无论您使用鼠标还是箭头键,都正确地执行边界

    *如果按住箭头键,则不会在边缘附近停止,因为平移加速会导致它在一步中“越过”边缘,所以它会在边缘附近停止(尝试同时按住箭头键)方向直到你碰到边缘,然后松开并再次按下它,通过一些解决方案,它会滚动一点)

    *碰到边缘时不会“反弹”

    *适当地强制缩放变化的界限

    编辑:好的,所以当您使用滚轮更改缩放时它可以工作,但不能使用缩放控件。让我玩一下,看看我是否也能让它工作......

    编辑 2:原来,问题是因为我删除了平移控件。只要存在平移控件,就可以正常使用滚轮和缩放控件。

    编辑 3:不……不是这样。我已经更新了处理缩放控件的代码。

    // bounds of the desired area
    var allowedBounds = new google.maps.LatLngBounds(
                        new google.maps.LatLng(-64, -64), 
                        new google.maps.LatLng(64, 64)
                        );
    
    var zoomChanged = false;
    
    google.maps.event.addListener(map, 'center_changed', function() {
      var mapBounds = map.getBounds();
    
      if(mapBounds.getNorthEast().lat() > allowedBounds.getNorthEast().lat()) {
        var newCenter = new google.maps.LatLng(map.getCenter().lat() -
                                               (mapBounds.getNorthEast().lat() -
                                               allowedBounds.getNorthEast().lat()),
                                               map.getCenter().lng(), true);
        map.panTo(newCenter);
        return;
      }
    
      if(mapBounds.getNorthEast().lng() > allowedBounds.getNorthEast().lng()) {
        var newCenter = new google.maps.LatLng(map.getCenter().lat(),
                                               map.getCenter().lng() -
                                               (mapBounds.getNorthEast().lng() -
                                               allowedBounds.getNorthEast().lng()), true);
        map.panTo(newCenter);
        return;
      }
    
      if(mapBounds.getSouthWest().lat() < allowedBounds.getSouthWest().lat()) {
        var newCenter = new google.maps.LatLng(map.getCenter().lat() +
                                               (allowedBounds.getSouthWest().lat() -
                                               mapBounds.getSouthWest().lat()),
                                               map.getCenter().lng(), true);
        map.panTo(newCenter);
        return;
      }
    
      if(mapBounds.getSouthWest().lng() < allowedBounds.getSouthWest().lng()) {
        var newCenter = new google.maps.LatLng(map.getCenter().lat(),
                                               map.getCenter().lng() +
                                               (allowedBounds.getSouthWest().lng() -
                                               mapBounds.getSouthWest().lng()), true);
        map.panTo(newCenter);
        return;
      }
    }, this);
    
    google.maps.event.addListener(map, 'zoom_changed', function() {
      zoomChanged = true;
    }, this);
    
    google.maps.event.addListener(map, 'bounds_changed', function() {
      if(zoomChanged) {   
        var mapBounds = map.getBounds();
    
        if(mapBounds.getNorthEast().lat() > allowedBounds.getNorthEast().lat()) {
          var newCenter = new google.maps.LatLng(map.getCenter().lat() -
                                                 (mapBounds.getNorthEast().lat() -
                                                 allowedBounds.getNorthEast().lat()),
                                                 map.getCenter().lng(), true);
          map.panTo(newCenter);
          return;
        }
    
        if(mapBounds.getNorthEast().lng() > allowedBounds.getNorthEast().lng()) {
          var newCenter = new google.maps.LatLng(map.getCenter().lat(),
                                                 map.getCenter().lng() -
                                                 (mapBounds.getNorthEast().lng() -
                                                 allowedBounds.getNorthEast().lng()), true);
          map.panTo(newCenter);
          return;
        }
    
        if(mapBounds.getSouthWest().lat() < allowedBounds.getSouthWest().lat()) {
          var newCenter = new google.maps.LatLng(map.getCenter().lat() +
                                                 (allowedBounds.getSouthWest().lat() -
                                                 mapBounds.getSouthWest().lat()),
                                                 map.getCenter().lng(), true);
          map.panTo(newCenter);
          return;
        }
    
        if(mapBounds.getSouthWest().lng() < allowedBounds.getSouthWest().lng()) {
          var newCenter = new google.maps.LatLng(map.getCenter().lat(),
                                                 map.getCenter().lng() +
                                                 (allowedBounds.getSouthWest().lng() -
                                                 mapBounds.getSouthWest().lng()), true);
          map.panTo(newCenter);
          return;
        }
    
        zoomChanged = false;
      }
    }, this);
    

    【讨论】:

    • 使用这种方法我得到“太多递归”错误。如果我只听 bounds_changed 事件(忽略 center_changed 和 zoom_changed),这个错误就会消失。另一方面,动作也不是 100% 完美,因为仍有一些反弹。
    • @JoseGómez 似乎存在特定于 Google Chrome 的问题,请在 Firefox 中尝试。我正在进一步研究它,看看我是否可以纠正这个问题。看到这个问题:stackoverflow.com/questions/15671480/…
    • @JoseGómez 我通过在 API 脚本包含行的查询字符串中设置 v=3 解决了这个问题。即&lt;script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3&amp;sensor=false"&gt;&lt;/script&gt;
    【解决方案2】:

    这是bug,如果您有兴趣,请在此问题上加注星标。

    有一个丑陋的解决方法:

    google.maps.event.addListener(map, 'zoom_changed', function () {
        google.maps.event.addListenerOnce(map, 'bounds_changed', function (e) {
                my_zoom_handler(); // do your job here
        });
    });
    

    【讨论】:

    • +1 我同意这是一个错误,对于这种情况,API 并不直观。如果在计算新边界后发送 zoom_change 就好了。
    • 如果bounds_changed 事件在缩放事件之前到达,此代码将不起作用。 Maps API fires these latter events independently.
    • 很好的解决方法。我将内部事件侦听器更改为'idle' 而不是'bounds_changed',因为在动画期间触发了'bounds_changed' 事件。我认为 OP 希望它在之后触发。
    • 太好了,谢谢;为我节省了很多谷歌和搜索解决方案,有超时和其他东西,这是最好的;
    • 一个问题,拖动事件也会受到绑定变化的影响;
    【解决方案3】:

    要绑定 bounds_changed 并在缩放后使用标记/地图内容,请使用:

    google.maps.event.addListener(map, 'zoom_changed', function() {
        this.zoomChanged = true;
    });
    
    google.maps.event.addListener(map,"bounds_changed",function() {
        if (this.zoomChanged) {
            this.zoomChanged = false;
            // DO YOUR STUFF
        }
    });
    

    【讨论】:

      【解决方案4】:

      来自API documentation

      如果您尝试检测视口中的变化,请务必使用特定的 bounds_changed 事件,而不是组成 zoom_changed 和 center_changed 事件。因为 Maps API 会独立触发后面的这些事件,所以 get_bounds() 可能不会报告有用的结果,直到视口已权威更改之后。如果您希望在此类事件之后获取 get_bounds(),请务必改为监听 bounds_changed 事件。

      【讨论】:

      • 在这种情况下使用 bounds_changed 事件而不是 zoom_changed 是无稽之谈。它会在更改边界的任何情况下触发,但他只对缩放更改的情况感兴趣。
      • @tomas-t 我不同意处理 bounds_changed 事件是“废话”。如果缩放更改时您在边界之后,您不能在您的 bounds_change 处理程序中检查 getZoom 吗?我发布的文档证明了这种行为(极端情况错误),但解决方法对我来说似乎很简单。
      • 当然可以,但是对于 OP 想要处理 bounds_changed 事件而不是 zoom_changed 的​​事情是不必要的,因为即使在平移等期间该事件也会触发。请查看我的回复中的解决方法。
      猜你喜欢
      • 1970-01-01
      • 2013-02-27
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多