219

我有一组要在嵌入式 Google 地图(API v3)上绘制的点。我希望边界能够容纳所有点,除非缩放级别太低(即,缩小太多)。我的方法是这样的:

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

gmap.fitBounds(bounds); 
gmap.setZoom( Math.max(6, gmap.getZoom()) );

这行不通。如果在 fitBounds 之后直接调用,最后一行“gmap.setZoom()”不会更改地图的缩放级别。

有没有办法在不将其应用于地图的情况下获得边界的缩放级别?解决这个问题的其他想法?

4

23 回答 23

368

编辑:见下面马特戴蒙德的评论。

知道了!试试这个:

map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() { 
  if (map.getZoom() > 16) map.setZoom(16); 
  google.maps.event.removeListener(listener); 
});

根据您的需要进行修改。

于 2010-10-31T20:41:33.377 回答
80

我在我的一个应用程序中解决了类似的问题。我对您对问题的描述感到有些困惑,但我认为您的目标与我的目标相同...

在我的应用程序中,我想绘制一个或多个标记并确保地图显示所有标记。问题是,如果我只依赖 fitBounds 方法,那么当只有一个点时,缩放级别就会被最大化——这不好。

解决的办法是点多的时候用fitBounds,只有一个点的时候用setCenter+setZoom。

if (pointCount > 1) {
  map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
  map.setCenter(mapBounds.getCenter());
  map.setZoom(14);
}
于 2010-07-16T18:23:22.617 回答
46

我已经多次访问此页面以获得答案,虽然所有现有答案都非常有帮助,但它们并没有完全解决我的问题。

google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
    var oldZoom = googleMap.getZoom();
    googleMap.setZoom(oldZoom - 1); //Or whatever
});

基本上我发现“zoom_changed”事件阻止了地图的 UI “跳过”,这在我等待“空闲”事件时发生。

希望这对某人有帮助!

于 2011-02-01T22:32:44.507 回答
11

我刚刚通过提前设置 maxZoom 来解决这个问题,然后再将其删除。例如:

map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });
于 2014-03-24T15:13:32.133 回答
5

请试试这个:

map.fitBounds(bounds);

// CHANGE ZOOM LEVEL AFTER FITBOUNDS
zoomChangeBoundsListener = google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  if (this.getZoom()){
    this.setZoom(15);
  }
});
setTimeout(function(){
  google.maps.event.removeListener(zoomChangeBoundsListener)
}, 2000);
于 2015-12-23T11:11:32.333 回答
4

如果我没记错的话,我假设您希望您的所有点都以尽可能高的缩放级别在地图上可见。我通过将地图的缩放级别初始化为16来实现这一点(不确定它是否是 V3 上可能的最高缩放级别)。

var map = new google.maps.Map(document.getElementById('map_canvas'), {
  zoom: 16,
  center: marker_point,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

然后在那之后我做了边界的东西:

var bounds = new google.maps.LatLngBounds();

// You can have a loop here of all you marker points
// Begin loop
bounds.extend(marker_point);
// End loop

map.fitBounds(bounds);

结果:成功!

于 2010-07-22T18:02:53.513 回答
3

我用:

gmap.setZoom(24); //this looks a high enough zoom value
gmap.fitBounds(bounds); //now the fitBounds should make the zoom value only less

这将根据您的代码使用 24 和必要的缩放级别中的较小者,但是它可能无论如何都会更改缩放并且不关心您缩小了多少。

于 2010-05-25T09:35:47.987 回答
3

我看到了许多不正确或过于复杂的解决方案,因此决定发布一个有效的、优雅的解决方案

setZoom()无法按预期工作的原因fitBounds()是异步的,因此它不能保证它会立即更新缩放,但您的调用setZoom()依赖于此。

您可能会考虑minZoom在调用之前设置地图选项fitBounds(),然后在完成后将其清除(这样用户仍然可以根据需要手动缩小):

var bounds = new google.maps.LatLngBounds();
// ... (extend bounds with all points you want to fit)

// Ensure the map does not get too zoomed out when fitting the bounds.
gmap.setOptions({minZoom: 6});
// Clear the minZoom only after the map fits the bounds (note that
// fitBounds() is asynchronous). The 'idle' event fires when the map
// becomes idle after panning or zooming.
google.maps.event.addListenerOnce(gmap, 'idle', function() {
  gmap.setOptions({minZoom: null});
});

gmap.fitBounds(bounds);

此外,如果您还想限制最大缩放,您可以对maxZoom属性应用相同的技巧。

请参阅MapOptions 文档

于 2017-05-19T22:22:57.243 回答
2

我有同样的问题,我能够使用以下代码解决它。此侦听器 ( google.maps.addListenerOnce()) 事件只会在map.fitBounds()执行后立即触发一次。所以,没必要

  1. 跟踪并手动删除侦听器,或
  2. 等到地图是idle

它最初设置适当的缩放级别,并允许用户放大和缩小超过初始缩放级别,因为事件侦听器已过期。例如,如果 onlygoogle.maps.addListener()被调用,那么用户将永远无法放大超过规定的缩放级别(在这种情况下为 4)。由于我们实施google.maps.addListenerOnce()了 ,用户将能够缩放到他/她选择的任何级别。

map.fitBounds(bounds);

var zoom_level_for_one_marker = 4;

google.maps.event.addListenerOnce(map, 'bounds_changed', function(event){
   if (this.getZoom() >= zoom_level_for_one_marker){  
       this.setZoom(zoom_level_for_one_marker) 
   }
});
于 2012-06-29T14:37:25.157 回答
2

有同样的问题,需要在地图上放置许多标记。这解决了我的情况:

  1. 声明界限
  2. koderoid 提供的使用方案(针对每个标记集bounds.extend(objLatLng)
  3. 地图完成后执行 fitbounds :

    google.maps.event.addListenerOnce(map, 'idle', function() { 
        map.fitBounds( bounds );
    });
    
于 2012-11-09T18:18:51.110 回答
2

我找到了一个解决方案,可以在打电话之前进行检查,fitBounds这样您就不会放大并突然缩小

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

var minLatSpan = 0.001;
if (bounds.toSpan().lat() > minLatSpan) {
    gmap.fitBounds(bounds); 
} else {
    gmap.setCenter(bounds.getCenter());
    gmap.setZoom(16);
}

您必须稍微使用一下 minLatSpan 变量才能将其放在您想要的位置。它将根据缩放级别和地图画布的尺寸而有所不同。

您也可以使用经度而不是纬度

于 2013-04-02T14:53:00.793 回答
1

在此函数中,您需要动态添加元数据以存储几何类型,仅因为该函数接受任何几何。

“fitGeometries”是一个扩展地图对象的 JSON 函数。

“几何”是一个通用的 javascript 数组,而不是 MVCArray()。

geometry.metadata = { type: "point" };
var geometries = [geometry];

fitGeometries: function (geometries) {
    // go and determine the latLngBounds...
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < geometries.length; i++) {
        var geometry = geometries[i];
        switch (geometry.metadata.type)
        {
            case "point":
                var point = geometry.getPosition();
                bounds.extend(point);
                break;
            case "polyline":
            case "polygon": // Will only get first path
                var path = geometry.getPath();
                for (var j = 0; j < path.getLength(); j++) {
                    var point = path.getAt(j);
                    bounds.extend(point);
                }
                break;
        }
    }
    this.getMap().fitBounds(bounds);
},
于 2010-07-16T14:15:41.710 回答
1

我使用它来确保缩放级别不超过设定级别,以便我知道卫星图像将可用。

为事件添加监听器zoom_changed。这还具有控制 UI 上的缩放控件的额外好处。

仅在setZoom需要时才执行,因此if语句优于Math.maxMath.min

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() > 19 ) { 
        map.setZoom(19); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

为防止缩小太多:

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() < 6 ) { 
        map.setZoom(6); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);
于 2010-07-21T06:26:38.420 回答
1

这项工作适用于我使用 API v3 但设置固定缩放:

var bounds = new google.maps.LatLngBounds();
// extend bounds with each point

gmap.setCenter(bounds.getCenter()); 
gmap.setZoom( 6 );
于 2013-03-13T13:46:33.263 回答
1

像我一样,如果你不愿意和听众一起玩,这是我想出的一个简单的解决方案:在地图上添加一个严格按照你的要求工作的方法,比如这个:

    map.fitLmtdBounds = function(bounds, min, max){
        if(bounds.isEmpty()) return;
        if(typeof min == "undefined") min = 5;
        if(typeof max == "undefined") max = 15;

        var tMin = this.minZoom, tMax = this.maxZoom;
        this.setOptions({minZoom:min, maxZoom:max});
        this.fitBounds(bounds);
        this.setOptions({minZoom:tMin, maxZoom:tMax});
    }

那么您可以调用map.fitLmtdBounds(bounds)而不是map.fitBounds(bounds)在定义的缩放范围下设置边界...或map.fitLmtdBounds(bounds,3,5)覆盖缩放范围..

于 2015-10-10T05:44:43.460 回答
0

请试试这个。

// Find out what the map's zoom level is
zoom = map.getZoom();
if (zoom == 1) {
  // If the zoom level is that low, means it's looking around the
world.
  // Swap the sw and ne coords
  viewportBounds = new
google.maps.LatLngBounds(results[0].geometry.location, initialLatLng);
  map.fitBounds(viewportBounds);
}

如果这对你有帮助。

祝一切顺利

于 2010-07-07T06:13:02.650 回答
0

我不喜欢建议,但如果你必须尝试 - 先打电话

gmap.fitBounds(bounds);

然后创建一个新的 Thread/AsyncTask,让它休眠 20-50ms 左右,然后调用

gmap.setZoom( Math.max(6, gmap.getZoom()) );

从 UI 线程(使用处理程序或onPostExecuteAsyncTask 的方法)。

我不知道它是否有效,只是一个建议。除此之外,您必须以某种方式自己根据您的点计算缩放级别,检查它是否太低,纠正它,然后调用gmap.setZoom(correctedZoom)

于 2010-07-17T01:33:00.280 回答
0

计算边界后,您可以检查左上角和右下角之间的距离;那么您可以通过测试距离来了解缩放级别(如果距离太远,缩放级别会很低)然后您可以选择是否使用 setbound 方法或 setZoom..

于 2010-07-20T12:16:44.417 回答
0

如果 'bounds_changed' 没有正确触发(有时 Google 似乎不能完全接受坐标),那么请考虑改用 'center_changed'。

每次调用 fitBounds() 时都会触发 'center_changed' 事件,尽管它会立即运行,而不必在地图移动后运行。

在正常情况下,'idle' 仍然是最好的事件监听器,但这可能有助于一些人在调用 fitBounds() 时遇到奇怪的问题。

查看谷歌地图 fitBounds 回调

于 2016-03-04T21:04:59.993 回答
0

加入另一个解决方案 - 我发现“监听 bounds_changed 事件然后设置新的缩放”方法对我来说并不可靠。我认为我有时会fitBounds在地图完全初始化之前调用,并且在fitBounds更改边界和缩放级别之前,初始化会导致会用完侦听器的 bounds_changed 事件。我最终得到了这段代码,到目前为止它似乎有效:

// If there's only one marker, or if the markers are all super close together,
// `fitBounds` can zoom in too far. We want to limit the maximum zoom it can
// use.
//
// `fitBounds` is asynchronous, so we need to wait until the bounds have
// changed before we know what the new zoom is, using an event handler.
//
// Sometimes this handler gets triggered by a different event, before
// `fitBounds` takes effect; that particularly seems to happen if the map
// hasn't been fully initialized yet. So we don't immediately remove the
// listener; instead, we wait until the 'idle' event, and remove it then.
//
// But 'idle' might happen before 'bounds_changed', so we can't set up the
// removal handler immediately. Set it up in the first event handler.

var removeListener = null;
var listener = google.maps.event.addListener(map, 'bounds_changed', () => {
  console.log(map.getZoom());
  if (map.getZoom() > 15) {
    map.setZoom(15);
  }

  if (!removeListener) {
    removeListener = google.maps.event.addListenerOnce(map, 'idle', () => {
      console.log('remove');
      google.maps.event.removeListener(listener);
    });
  }
});
于 2018-03-05T12:57:19.637 回答
0

对我来说,最简单的解决方案是:

map.fitBounds(bounds);

function set_zoom() {
    if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
    else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);
于 2018-03-23T19:09:39.117 回答
-1
google.maps.event.addListener(marker, 'dblclick', function () {
    var oldZoom = map.getZoom(); 
    map.setCenter(this.getPosition());
    map.setZoom(parseInt(oldZoom) + 1);
});
于 2013-12-05T11:13:34.333 回答
-3

我所做的只是:

map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

它适用于 V3 API。

于 2010-07-28T10:36:07.760 回答