Google Maps v3:强制执行 使用fitBounds时的缩放级别


79

我正在地图上绘制一系列标记(使用maps api的v3)。

在v2中,我有以下代码:

  bounds = new GLatLngBounds();

  ... loop thru and put markers on map ...
  bounds.extend(point);
  ... end looping

  map.setCenter(bounds.getCenter());
  var level = map.getBoundsZoomLevel(bounds);
  if ( level == 1 ) 
    level = 5;
  map.setZoom(level > 6 ? 6 : level);

而且可以很好地确保地图上始终显示适当级别的细节。

我正在尝试在v3中复制此功能,但setZoom和fitBounds似乎不配合:

... loop thru and put markers on the map
  var ll = new google.maps.LatLng(p.lat,p.lng);
  bounds.extend(ll);
... end loop

var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);
map.fitBounds(bounds);

我尝试了不同的排列(例如,在setZoom之前移动fitBounds),但是我对setZoom所做的任何操作似乎都不会影响地图。我想念什么吗?有没有办法做到这一点?

Answers:


137

关于Google网上论坛的讨论中,我发现基本上当您执行fitBounds时,缩放是异步发生的,因此您需要捕获zoom和bounds change事件。最后一篇文章中的代码为我做了一点修改,因为它可以阻止您完全放大15倍以上,因此使用第四篇文章中的想法将标志设置为仅在第一次使用。

// Do other stuff to set up map
var map = new google.maps.Map(mapElement, myOptions);
// This is needed to set the zoom after fitbounds, 
google.maps.event.addListener(map, 'zoom_changed', function() {
    zoomChangeBoundsListener = 
        google.maps.event.addListener(map, 'bounds_changed', function(event) {
            if (this.getZoom() > 15 && this.initialZoom == true) {
                // Change max/min zoom here
                this.setZoom(15);
                this.initialZoom = false;
            }
        google.maps.event.removeListener(zoomChangeBoundsListener);
    });
});
map.initialZoom = true;
map.fitBounds(bounds);

希望能有所帮助,

安东尼


3
这是一个好方法。另一种方法是检查当前边界并扩展边界,即stackoverflow.com/questions/3334729/…。尽管这里的链接答案只是将边界扩大了一个分数,但是您可以使用相同的方法将边界扩大一个更大的数目;我发现将7加到所有角上都很好。
Metro Smurf

2
我想纠正我以前的评论。我认为可能需要设置initialZoom属性。忽略了那部分代码后,我在放大IE 9时遇到了一些麻烦...不错的解决方案!
安德鲁

21
使用google.maps.event.addListenerOnce(),因此您不必随后手动删除侦听器。
pstadler 2013年

5
因为我已经第三次看这了,所以这里是高尔夫球版。谢谢@pstadler。google.maps.event.addListenerOnce(map, 'bounds_changed', function() { this.setZoom(Math.min(15, this.getZoom())); });
sba 2015年

1
使用addLIstenerOnce时,您可以简单地听zoom_changed。我zoom_changed刚刚使用过map.fitBounds(bounds);,似乎在Chrome上运行良好。
牛奶人

63

如果不尝试,我想说您应该能够通过fitBounds()获得缩放级别来做到这一点,即

map.fitBounds(bounds);
var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);

如果您尝试过但没有成功,则可以minZoomMapOptions (api-reference)中使用设置地图,如下所示:

var map = new google.maps.Map(document.getElementById("map"), { minZoom: 6 });

使用时,可以防止地图进一步缩小fitBounds()


一个简单而优雅的解决方案!
Falantar014 2013年

3
设置minZoom和maxZoom值会限制用户缩放超出这些值,因此,如果您只想将初始缩放设置为合理的值(这就是我认为OP在谈论的内容)就
无济于事

5
所以基本上与我在答案中写的完全一样吗?
Flygenring 2014年

@Izazael提出了一个很好的观点,答案中没有提到。这可以阻止fitBounds()缩放得太远,但同时也限制了用户与地图缩放按钮的交互。如果您希望用户完全控制,则可接受的答案是更好的选择。
Rich Court

1
可能因为新版本而无法正常工作。fitBounds()异步工作!
RubbelDeCatc

19

您还可以在调用fitBounds()之前设置maxZoom选项,然后再重置该值:

if(!bounds.isEmpty()) {
    var originalMaxZoom = map.maxZoom;
    map.setOptions({maxZoom: 18});
    map.fitBounds(bounds);
    map.setOptions({maxZoom: originalMaxZoom});
}

我喜欢这个选项,因为它不会zoom_changed像其他许多选项一样导致事件触发两次
Greg

当max对象定义了maxZoom选项时,这是一个很棒的解决方案。
Alexey Domanski

17

安东尼的解决方案非常好。我只需要固定初始页面加载的缩放比例(以确保您不会过分放大即可),这对我来说是成功的窍门:

var zoomChangeBoundsListener =
    google.maps.event.addListener(map, 'bounds_changed', function(event) {
        google.maps.event.removeListener(zoomChangeBoundsListener);
        map.setZoom( Math.min( 15, map.getZoom() ) );
    });


map.fitBounds( zoomBounds );

5
除了可以删除监听器之外,您可以使用addListenerOnce,但是我正在使用此解决方案。
Derek S

11

当您在一项上调用map.fitBounds()时,地图可能会放大得太近。要解决此问题,只需将“ maxZoom”添加到mapOptions ...

var mapOptions = {
  maxZoom: 15
};

7

就我而言,我只是想将缩放级别设置为比fitBounds期间google地图为我选择的缩放级别小一个。目的是使用fitBounds,但还要确保在任何地图工具等下都没有标记。

我的地图是早期创建的,然后页面上的许多其他动态组件都有机会添加标记,每次添加之后都调用fitBounds。

这是在最初创建地图对象的初始块中。

var mapZoom = null;

然后将其添加到每个添加了标记的块中,就在map.fitBounds被调用之前...

google.maps.event.addListenerOnce(map, 'bounds_changed', function() { 
    if (mapZoom != map.getZoom()) { 
        mapZoom = (map.getZoom() - 1); 
        map.setZoom(mapZoom); 
    } 
});

在未进行检查的情况下使用“ bounds_changed”时,无论是否需要,每个地图都会缩小一次。相反,当我使用'zoom_changed'时,有时在地图工具下会有标记,因为缩放实际上并没有改变。现在它总是被触发的,但是检查确保它仅在需要时才缩小一次。

希望这可以帮助。


这似乎是唯一应该实际使用的答案,addListener而不是addListenerOnce在每个单身之前重复(和依靠记忆)map.fitBounds()
Flygenring

3

由于Google Maps V3是事件驱动的,因此可以在zoom_changed事件触发时告诉API将缩放比例设置回适当的

var initial = true
google.maps.event.addListener(map, "zoom_changed", function() {
    if (initial == true){
       if (map.getZoom() > 11) {
         map.setZoom(11);
         initial = false;
       }
    }
}); 

我使用initial来使最终的fitBounds永久填充时地图不会缩放太多,而是让用户根据自己的需要进行缩放。如果没有该条件,则用户可能会发生超过11个的缩放事件。


2

我发现以下内容可以很好地工作。这是Ryan对https://stackoverflow.com/questions/3334729 / ...回答的一种变体。它保证显示的面积至少是度值的两倍。offset

const center = bounds.getCenter()
const offset = 0.01
const northEast = new google.maps.LatLng(
    center.lat() + offset,
    center.lng() + offset
)
const southWest = new google.maps.LatLng(
    center.lat() - offset,
    center.lng() - offset
)
const minBounds = new google.maps.LatLngBounds(southWest, northEast)
map.fitBounds(bounds.union(minBounds))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.