【问题标题】:Using setZoom() after using fitBounds() with Google Maps API V3在将 fitBounds() 与 Google Maps API V3 一起使用后使用 setZoom()
【发布时间】:2025-12-19 15:25:06
【问题描述】:

我正在使用 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() 神奇地开始运行。

任何想法我如何解决这个问题?如果无法正常工作,我正在考虑设置一个 maxZoom 级别作为替代方案。

【问题讨论】:

  • .map.map 是故意放在那里还是有错误?如果可能的话,上传一个测试页面并提供一个链接,这样我们可以更轻松地看到问题。
  • 我遇到了同样的问题。很想知道解决方法。
  • .map.map 是故意的。第一个指的是我的地图对象,第二个指的是谷歌地图对象。我已经从我的代码中清除了这个问题。

标签: javascript google-maps google-maps-api-3 google-maps-markers


【解决方案1】:

好的,我想通了。显然,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 的答案以获得不需要超时的更好解决方案。

【讨论】:

  • 不错的解决方案,也对我有用。尽管您可以完成 addListenerOnce(),这将取消 removeListener() 调用。
  • 除了使用 addListenerOnce,我建议使用 setTimeout 来移除监听器。我有一个案例,边界没有改变,因为标记彼此非常接近。使用此代码,用户将无法缩放(至少一次)。
  • @MikePurcell & h0tw1r3:我编辑了代码以添加您的建议,谢谢!没有测试,所以希望我没有引入任何愚蠢的错误。
  • @Herman .....thnx herman 我已经在这个问题上坚持了大约 3 个小时......再次thnx......
  • 我不得不将 removeListener 放在 addListener 回调函数中。否则执行会在调用它之前移除监听器。
【解决方案2】:
google.maps.event.addListenerOnce(yourMap, 'bounds_changed', function(event) {
  if (this.getZoom() > 15) {
    this.setZoom(15);
  }
});

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

【讨论】:

  • 很好的解决方案。可以通过使用google.maps.event.addListenerOnce 而不是添加然后删除侦听器来使其更好。
  • 我冒昧地编辑了答案以使用addListenerOnce
  • 那个解决方案对我不起作用。 this.getZoom() 在回调中总是未定义,this.setZoom() 没有任何作用。
  • 完美,最佳答案
  • 记住使用 this 的问题 我会改为使用对传递给事件处理程序的映射的引用,如下所示:if (yourMap.getZoom() > 15) { ... }。听起来@horace 有问题,这可能是指正在完成实现的当前类或google.maps.event 实例。如果您只想使用传入的地图引用,请避免使用它。
【解决方案3】:

我发现额外的缩放有点刺耳。如果您在调用 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
    });
});

【讨论】:

  • 更好的解决方案,因为在更改边界后设置缩放(如其他答案所建议的那样)不会很顺利,实际上会非常难看。
【解决方案4】:

我有简单而肮脏的解决方案。
使用 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++;

【讨论】:

  • 但是你知道为什么两者不一起工作吗?我不明白为什么这些在串行调用时不兼容。
【解决方案5】:

我只是在函数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;
    },

【讨论】:

    【解决方案6】:

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

    我想出了这个效果很好的解决方案:

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

    【讨论】: