我遇到了一个调用map.fitBounds似乎缩小的问题。我正在尝试使用backbone.js路由器来保存网址中的地图边界。我希望能够为网址添加书签,然后让地图看起来完全一样。
我注意到在控制台中调用map.fitBounds(map.getBounds())
将始终缩小。我想在哪里不改变地图。
这是正常行为吗?我如何强制执行此操作,以使地图从一个步骤到下一个步骤看起来相同?
由于
答案 0 :(得分:12)
Google Map API的这个问题已经讨论过几次了。参见:
函数map.fitBounds()
将视口设置为包含边界。但是map.getBounds()
函数返回带有一些额外边距的视口边界(请注意,这是正常行为,没有错误)。放大的边界不再适合上一个视口,因此地图会缩小。
解决问题的一个简单方法是使用地图中心和缩放级别。查看函数map.getCenter()
,map.setCenter()
,map.getZoom()
和map.setZoom()
。
答案 1 :(得分:4)
在将边界框发送到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边界初始化地图。这个解决方案非常有效。
Google地图基本上是在调用fitBounds()
时执行此操作:
如果给定的界限完全与视口匹配,则Google地图不会将其视为"包含"边界,所以它缩小了一个级别。
答案 2 :(得分:3)
对于在2018年看到此问题的人,Google Maps API v3现在支持第二个padding
参数,该参数指定要包含在您指定的边界周围的填充量。
要避免缩小,只需使用fitBounds
的填充调用0
即可。对于此示例,它将是map.fitBounds(map.getBounds(), 0)
答案 3 :(得分:2)
初始化名为map.fitBounds(...)
的地图后,我遇到了同样的问题。我遇到的行为是,如果初始化地图后几秒钟调用了fitBounds
方法,那么就没问题了(缩放是适当的)。
因此,我首先在加载地图后开始调用fitBounds
方法,在Google地图上,该方法将转换为idle
的时间。
google.maps.event.addListener(map, 'idle', function() {
var bounds = //define bounds...
map.fitBounds(bounds);
});
这实际上有效,但是idle
事件几乎总是被触发。如果此更改停止后地图发生任何变化(拖动,缩放等),则地图将再次适合边界...
问题在于,仅一次调用该方法就不会不起作用(使用布尔值来检查是否已被调用,或者使用google.maps.event.addListenerOnce
,因为映射第一次空闲时,它仍然“不是“还没准备好”以适应边界。(根据经验)。
所以我的解决方案是要在其他事件上触发fitBounds
。事件idle
实际上可以完成工作(仅被调用一次),而不是为fitBounds
方法调用得太早的tilesloaded
!
解决方案:
google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
var bounds = //define bounds...
map.fitBounds(bounds);
});
答案 4 :(得分:0)
我也注意到了这个问题。我的解决方案是将map.getBounds()
与我设置界限进行比较;如果它们是相同的,我正在跳过map.fitBounds()
电话。
答案 5 :(得分:0)
我遇到了同样的问题,@ Tomik的回答帮助我解决了这个问题。这是我使用的代码片段。
保存上一个缩放和居中。
const lastMapZoom = this.map.getZoom();
const lastMapCenter = this.map.getCenter();
要重新设置值。
this.map.setCenter(lastMapZoom);
this.map.setZoom(lastMapCenter);
答案 6 :(得分:0)
当我在隐藏的地图视图上使用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);
});
}
注意:我在setTimeout
调用周围包裹了fitBounds()
,以便Angular可以完成生命周期并在调用地图之前对其进行渲染。