我遇到了一个问题,调用map.fitBounds似乎会缩小地图。 我试图使用backbone.js路由器将地图边界保存在url中。我想能够将url加为书签,以后再回来时地图看起来完全相同。
我注意到在控制台中调用map.fitBounds(map.getBounds())
总是会缩小地图。 而我希望它不会改变地图。
这是正常行为吗?我该如何强制执行,使地图在每一步都看起来相同?
谢谢
我遇到了一个问题,调用map.fitBounds似乎会缩小地图。 我试图使用backbone.js路由器将地图边界保存在url中。我想能够将url加为书签,以后再回来时地图看起来完全相同。
我注意到在控制台中调用map.fitBounds(map.getBounds())
总是会缩小地图。 而我希望它不会改变地图。
这是正常行为吗?我该如何强制执行,使地图在每一步都看起来相同?
谢谢
对于在2018年之后查看此问题的人,Google Maps API v3现在支持第二个padding
参数,该参数指定您指定的边界周围要包含的填充量。
为了避免缩小地图,请只需使用填充值为0
来调用fitBounds
。 对于这个例子,它将是map.fitBounds(map.getBounds(), 0)
。
讨论了 Google Map API 的这个问题多次。请参见:
map.fitBounds()
函数将视图设置为包含边界框。但是 map.getBounds()
函数返回的视口边界带有一些额外的边距(请注意,这是正常行为,而不是 bug)。扩大后的边界不再适合之前的视口,因此地图会缩小。
解决问题的简单方法是改用地图中心和缩放级别。请参见函数 map.getCenter()
、map.setCenter()
、map.getZoom()
和 map.setZoom()
。
在将边界框发送到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本质上会执行以下操作:
如果给定的边界恰好匹配视口,则Google Maps不认为其“包含”该边界,因此它会再缩小一级。
在初始化地图调用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);
});
我在使用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()
时。半秒钟的延迟足够让地图中的所有内容重置。 - lhanfitBounds()
。谢谢。 - alstr我也注意到了这个问题。我的解决方案是将map.getBounds()
与我设置的边界进行比较;如果它们相同,我就跳过map.fitBounds()
调用。
我遇到了同样的问题,@Tomik的答案帮助我解决了它。这是我使用的代码片段。
保存先前的缩放和中心。
const lastMapZoom = this.map.getZoom();
const lastMapCenter = this.map.getCenter();
将值设定回去。
this.map.setCenter(lastMapCenter);
this.map.setZoom(lastMapZoom);