Google Maps v3:强制执行最低要求。使用 fitBounds 时的缩放级别

Posted

技术标签:

【中文标题】Google Maps v3:强制执行最低要求。使用 fitBounds 时的缩放级别【英文标题】:Google Maps v3: Enforcing min. zoom level when using 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 所做的一切似乎都不会影响地图。我错过了什么吗?有没有办法做到这一点?

【问题讨论】:

【参考方案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);

希望对你有帮助,

安东尼。

【讨论】:

这是个好方法。另一种方法是检查当前边界并扩展边界,即 ***.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 的 answer 到 https://***.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);

【讨论】:

以上是关于Google Maps v3:强制执行最低要求。使用 fitBounds 时的缩放级别的主要内容,如果未能解决你的问题,请参考以下文章

在 Google Maps V3 API 标记鼠标悬停时获取鼠标光标的位置

Google Maps v3 fitBounds() 对单个标记来说太近了

Google Maps V3 渲染超过 100 万个标记(在合理的时间内)

是否可以在Google Maps API v3上编写自定义文字?

是否可以在 Google Maps API v3 上编写自定义文本?

Google Maps v3和JQuery选项卡(JQuery选项卡Google Maps bug)