谷歌地图API 3在使用fitBounds时会缩小地图视野

14

我遇到了一个问题,调用map.fitBounds似乎会缩小地图。 我试图使用backbone.js路由器将地图边界保存在url中。我想能够将url加为书签,以后再回来时地图看起来完全相同。

我注意到在控制台中调用map.fitBounds(map.getBounds())总是会缩小地图。 而我希望它不会改变地图。

这是正常行为吗?我该如何强制执行,使地图在每一步都看起来相同?

谢谢


https://dev59.com/jHA75IYBdhLWcg3wg5Zh#51270624 对我有用。 - Kayote
7个回答

17

对于在2018年之后查看此问题的人,Google Maps API v3现在支持第二个padding参数,该参数指定您指定的边界周围要包含的填充量。

为了避免缩小地图,请只需使用填充值为0来调用fitBounds。 对于这个例子,它将是map.fitBounds(map.getBounds(), 0)


14

讨论了 Google Map API 的这个问题多次。请参见:

map.fitBounds()函数将视图设置为包含边界框。但是 map.getBounds() 函数返回的视口边界带有一些额外的边距(请注意,这是正常行为,而不是 bug)。扩大后的边界不再适合之前的视口,因此地图会缩小。

解决问题的简单方法是改用地图中心和缩放级别。请参见函数 map.getCenter()map.setCenter()map.getZoom()map.setZoom()


2
我花了16个小时才到这里。即使这不是一个错误,也应该为那些试图完成此操作的人提供一些解决方案。 - Yugal Jindle

4

在2017年解决这个问题

在将边界框发送到map.fitBounds()之前,稍微缩小一下边界框。

以下是一个缩小边界框的函数:

// Values between 0.08 and 0.28 seem to work
// Any lower and the map will zoom out too much
// Any higher and it will zoom in too much
var BOUNDS_SHRINK_PERCENTAGE = 0.08; // 8%

/**
 * @param  {google.maps.LatLngLiteral} southwest
 * @param  {google.maps.LatLngLiteral} northeast
 * @return {Array[google.maps.LatLngLiteral]}
 */
function slightlySmallerBounds(southwest, northeast) {
  function adjustmentAmount(value1, value2) {
    return Math.abs(value1 - value2) * BOUNDS_SHRINK_PERCENTAGE;
  }

  var latAdjustment = adjustmentAmount(northeast.lat, southwest.lat);
  var lngAdjustment = adjustmentAmount(northeast.lng, southwest.lng);

  return [
    {lat: southwest.lat + latAdjustment, lng: southwest.lng + lngAdjustment},
    {lat: northeast.lat - latAdjustment, lng: northeast.lng - lngAdjustment}
  ]
}

使用方式如下:

// Ensure `southwest` and `northwest` are objects in google.maps.LatLngLiteral form:
// southwest == {lat: 32.79712, lng: -117.13931}
// northwest == {lat: 32.85020, lng: -117.09356}

var shrunkBounds = slightlySmallerBounds(southwest, northeast);
var newSouthwest = shrunkBounds[0];
var newNortheast = shrunkBounds[1];

// `map` is a `google.maps.Map`
map.fitBounds(
  new google.maps.LatLngBounds(newSouthwest, newNortheast)
);

我有一个应用程序与codr做的事情一样:在URL中保存当前地图范围,并在刷新时从URL边界初始化地图。这个解决方案非常有效。

为什么这能行?

当调用fitBounds()时,Google Maps本质上会执行以下操作:

  1. 将地图居中于给定边界框的中心点。
  2. 缩放到最高的缩放级别,其中视区将包含在视口框内的给定边界。

如果给定的边界恰好匹配视口,则Google Maps不认为其“包含”该边界,因此它会再缩小一级。


4

在初始化地图调用map.fitBounds(...)后,我遇到了同样的问题。 我遇到的行为是,如果在地图初始化后几秒钟后调用fitBounds方法,则没有问题(缩放是适当的)。 因此,我首先在地图加载后调用fitBounds方法,在谷歌地图上翻译为地图处于idle状态时。

google.maps.event.addListener(map, 'idle', function() {
   var bounds = //define bounds...
   map.fitBounds(bounds);
});

这个方法实际上是有效的,但是 idle 事件触发得非常频繁。如果地图有任何变化(拖动、缩放等),当这些变化停止时,地图将再次适应边界...

问题在于仅调用一次该方法不起作用(无论是使用布尔值检查是否已调用还是使用 google.maps.event.addListenerOnce),因为第一次地图空闲时它仍然“没有准备好”适应边界(根据经验)。

所以我的解决方案是在另一个事件上触发 fitBounds。与太早调用 fitBounds 方法的 idle 事件不同,tilesloaded 事件实际上完成了任务(只调用一次)!

解决方案:

google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
   var bounds = //define bounds...
   map.fitBounds(bounds);
});

2

我在使用fitBounds()时注意到了这种行为,它是在隐藏的地图视图上使用的(使用前端渲染框架,如Angular)。因为这是一个移动视图,我首先显示了一个位置列表,并在加载列表时填充了隐藏地图上的标记(并发加载)。因此,当用户想要查看地图并切换段视图/选项卡/任何其他内容时,地图将显示已经加载并在视图中的标记。但是这个问题导致地图出现错误,并缩放以显示完整的世界地图。

<div [hidden]="view !== 'map'>
    <google-map></google-map>
</div>

fitBounds() 需要在视图中加载地图,因为它使用地图的尺寸来调整地图大小。如果地图被隐藏,它会缩放地图直到完整地图显示。

解决方案很简单:当视图切换时,再次调用 fitBounds()

<button (click)="showMap()">Show Map</button>

public showMap() {
    this.view = 'map';
    setTimeout(() => {
        if (typeof this.map !== 'undefined') this.map.fitBounds(this.bounds);
    });
}

注意:我在fitBounds()调用周围包装了一个setTimeout,以便Angular可以完成生命周期并在调用之前呈现地图。

我遇到了完全相同的情况,这是对我有用的修复方法。我想指出,在我的情况下,我只是使用了setTimeout并等待了500毫秒,因为this.map已经在我的页面上定义了。问题只发生在执行show()hide(),然后再次执行show()时。半秒钟的延迟足够让地图中的所有内容重置。 - lhan
我在Django网站上使用了一个隐藏的地图,这是问题所在。我发现必须让地图真正可见才能正确地使用fitBounds()。谢谢。 - alstr

0

我也注意到了这个问题。我的解决方案是将map.getBounds()与我设置的边界进行比较;如果它们相同,我就跳过map.fitBounds()调用。


0

我遇到了同样的问题,@Tomik的答案帮助我解决了它。这是我使用的代码片段。

保存先前的缩放和中心。

const lastMapZoom = this.map.getZoom();
const lastMapCenter = this.map.getCenter();

将值设定回去。

this.map.setCenter(lastMapCenter);
this.map.setZoom(lastMapZoom);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接