使用Google Maps API V3,在使用fitBounds()函数后使用setZoom()函数。

83

我正在使用fitBounds()函数来设置地图的缩放级别,以包括当前显示的所有标记。但是,当仅有一个标记可见时,缩放级别为100%(我认为是缩放级别20)。然而,我不希望它缩放得那么远,这样用户就可以调整标记的位置而无需缩小。

以下是我的代码:

var marker = this.map.createMarker(view.latlng, this.markerNumber);
this.map.bounds.extend(view.latlng);
this.map.map.setCenter(this.map.bounds.getCenter());
this.map.map.fitBounds(this.map.bounds);
if (this.markerNumber === 1) {
  this.map.map.setZoom(16);
}
this.markerNumber++;

其中this.map.bounds先前被定义为:

this.map.bounds = new google.maps.LatLngBounds();

然而,我遇到的问题是,当我使用 this.map.map.fitBounds(this.map.bounds); 这行代码时,this.map.map.setZoom(16); 这行代码就无法工作。但是,当我注释掉 fitBound() 这一行代码时,setZoom() 就神奇地开始正常运行了。

有没有什么想法可以解决这个问题?如果无法使其正常工作,我正在考虑将最大缩放级别设置为替代方案。


“.map.map” 是故意这样写的还是错误?如果可能,请上传一个测试页面并提供链接,以便我们更容易地看到问题。 - Argiropoulos Stavros
我也遇到了同样的问题。很想知道解决方法。 - Herman Schaaf
.map.map 是有意为之的。第一个指的是我的地图对象,第二个指的是谷歌地图对象。我已经从代码中清除了这个问题。 - Andrew De Andrade
请参见以下链接:https://dev59.com/JHE95IYBdhLWcg3wI6jt - Mawg says reinstate Monica
6个回答

117

好的,我想通了。 显然,fitbounds() 是异步的,因此在设置缩放级别前必须等待bounds_changed事件。

map = this.map.map;

map.fitBounds(this.map.bounds);
zoomChangeBoundsListener = 
    google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
        if (this.getZoom()){
            this.setZoom(16);
        }
});
setTimeout(function(){google.maps.event.removeListener(zoomChangeBoundsListener)}, 2000);

更新:请参考 @Nequin 的答案,使用 addListenerOnce 可以得到一种更好的解决方案,而不需要使用超时。


10
不错的解决方法,对我也起作用。虽然你可以使用addListenerOnce()来代替removeListener()调用。 - Mike Purcell
2
除了使用addListenerOnce之外,我建议使用setTimeout来删除侦听器。我曾经遇到过这样的情况,即由于标记物彼此靠近,边界没有改变。使用这段代码后,用户将无法缩放(至少一次)。 - h0tw1r3
@MikePurcell和h0tw1r3:我编辑了代码以添加你们的建议,谢谢!没有测试过,所以希望我没有引入任何愚蠢的错误。 - Herman Schaaf
@ Herman……谢谢你,我在这个问题上卡了约3个小时……再次感谢…… - Usman
1
我必须将removeListener放在addListener回调函数内部。否则,执行会在调用它之前删除侦听器。 - Arman Bimatov
显示剩余3条评论

109
google.maps.event.addListenerOnce(yourMap, 'bounds_changed', function(event) {
  if (this.getZoom() > 15) {
    this.setZoom(15);
  }
});

这个解决方案工作得更好……而不是等待超时来删除监听器。在使用fitBounds之前直接调用它(我相信之后调用也可以)。


4
好的解决方案,可以通过使用 google.maps.event.addListenerOnce 而不是添加然后删除监听器来使其更好。 - chuck w
3
我已经帮您修改了答案,使用了 addListenerOnce - Mathias Bynens
1
那个解决方案对我不起作用。在回调函数中,this.getZoom()总是未定义的,而this.setZoom()没有任何效果。 - horace
完美,最佳答案 - 00-BBB
记住使用this会产生问题,我建议改为使用传递给事件处理程序的地图引用,例如:if (yourMap.getZoom() > 15) { ... }。听起来@horace对此有问题,可能是因为它指的是正在进行实现的当前类或google.maps.event实例。如果您只想使用传入的地图引用,请避免使用this。 - Sparker73

16

我觉得额外的缩放有点突兀。如果你在调用fitBounds之前设置maxZoom选项(然后在回调中取消设置),就可以避免这种情况:

我发现额外的缩放有点让人感到不适。如果在调用fitBounds之前设置了maxZoom选项(并在回调函数中取消设置),则可以避免这种情况:

map.setOptions({
    maxZoom: 10
});

map.setCenter(new google.maps.LatLng(-89, -179)); // make sure it changes so the idle listener gets called back

map.fitBounds(bounds);

var listener = google.maps.event.addListenerOnce(map, "idle", function()
{
    map.setOptions({
        maxZoom: 999
    });
});

更好的解决方案,因为在边界改变后设置缩放比例(正如其他答案所建议的)不会很平滑,实际上会非常丑陋。 - Pedro Estevão

2

我有一个简单且不太优雅的解决方案。
使用if else语句...

var marker = this.map.createMarker(view.latlng, this.markerNumber);
this.map.bounds.extend(view.latlng);
this.map.map.setCenter(this.map.bounds.getCenter()); 
if (this.markerNumber === 1) {
  this.map.map.setZoom(16);
} else {
   this.map.map.fitBounds(this.map.bounds);
}       
this.markerNumber++;

1
但是你知道为什么这两个不能一起工作吗?我不明白为什么在串行调用时它们是不兼容的。 - Andrew De Andrade

1
我只是在函数 addBounds(position) 中添加了一行代码,就解决了问题,如下所示:
    addBounds: function(position) {
        this.get('bounds', new google.maps.LatLngBounds()).extend(this._latLng(position));
        this.get('map').fitBounds(this.get('bounds'));
        this.get('map').setZoom(16);//line added
        return this;
    },

0

所有带有事件监听器的解决方案对我都不起作用(回调函数中的this.getZoom()总是未定义,而this.setZoom()没有效果)。

我想出了这个可行的解决方案:

function set_zoom() {
    if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
    else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);

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