我想在嵌入式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()”不会更改地图的缩放级别。
有没有办法获得边界的缩放级别而不将其应用到地图?其他想法可以解决这个问题吗?
答案 0 :(得分:323)
编辑:请参阅下面的Matt Diamond的评论。
知道了!试试这个:
map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() {
if (map.getZoom() > 16) map.setZoom(16);
google.maps.event.removeListener(listener);
});
根据您的需要进行修改。
答案 1 :(得分:65)
我在其中一个应用中解决了类似的问题。你对问题的描述让我感到有些困惑,但我认为你有同样的目标......
在我的应用程序中,我想绘制一个或多个标记,并确保地图显示所有标记。问题是,如果我完全依赖于fitBounds方法,那么当存在单个点时,缩放级别将被最大化 - 这是不好的。
解决方案是在有多个点时使用fitBounds,在只有一个点时使用setCenter + setZoom。
if (pointCount > 1) {
map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
map.setCenter(mapBounds.getCenter());
map.setZoom(14);
}
答案 2 :(得分:43)
我多次来到这个页面得到答案,虽然所有现有答案都非常有用,但他们并没有完全解决我的问题。
google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
var oldZoom = googleMap.getZoom();
googleMap.setZoom(oldZoom - 1); //Or whatever
});
基本上我发现'zoom_changed'事件阻止了地图的UI“跳过”,这是在我等待“空闲”事件时发生的。
希望这有助于某人!
答案 3 :(得分:10)
我刚刚通过提前设置maxZoom来修复此问题,然后将其删除。例如:
map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });
答案 4 :(得分: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);
结果: 成功了!
答案 5 :(得分: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和必要的缩放级别,但它可能会改变缩放,而不关心缩小的数量。
答案 6 :(得分:2)
我看到许多不正确或太复杂的解决方案,所以决定发布一个工作,优雅的解决方案。
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 docs。
答案 7 :(得分:2)
有同样的问题,需要在地图上放置许多标记。 这解决了我的情况:
bounds.extend(objLatLng)
)地图完成后执行合适的地方:
google.maps.event.addListenerOnce(map, 'idle', function() {
map.fitBounds( bounds );
});
答案 8 :(得分: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变量来获取它想要的位置。它将根据缩放级别和地图画布的尺寸而变化。
您也可以使用经度代替纬度
答案 9 :(得分:2)
请试试这个:
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);
答案 10 :(得分:1)
我使用此功能确保缩放级别不超过设定级别,以便我知道卫星图像可用。
为zoom_changed
事件添加侦听器。
这还具有控制UI上的缩放控制的附加好处。
如果需要,只执行setZoom
,因此if
语句优先于Math.max
或Math.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);
答案 11 :(得分:1)
在此函数中,您需要动态添加元数据以存储几何类型,因为该函数接受任何几何体。
“fitGeometries”是一个扩展地图对象的JSON函数。
“geometry”是一个通用的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);
},
答案 12 :(得分:1)
我有同样的问题,我可以使用以下代码解决它。此侦听器(google.maps.addListenerOnce()
)事件只会在map.fitBounds()
执行后立即触发一次。所以,没有必要
idle
。它最初设置了适当的缩放级别,并允许用户放大和缩小超过初始缩放级别,因为事件侦听器已过期。例如,如果仅调用google.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)
}
});
答案 13 :(得分:1)
这项工作适用于API v3,但设置了固定缩放:
var bounds = new google.maps.LatLngBounds();
// extend bounds with each point
gmap.setCenter(bounds.getCenter());
gmap.setZoom( 6 );
答案 14 :(得分: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)
覆盖缩放范围..
答案 15 :(得分:0)
如果&#39; bounds_changed&#39;没有正确启动(有时谷歌似乎没有完全接受坐标),然后考虑使用&#39; center_changed&#39;代替。
&#39; center_changed&#39;每次调用fitBounds()时都会触发事件,尽管它会立即运行,而不一定在地图移动后运行。
在正常情况下,&#39;闲置&#39;仍然是最好的事件监听器,但这可能会帮助一些人通过fitBounds()调用遇到奇怪的问题。
答案 16 :(得分:0)
使用另一种解决方案 - 我发现&#34;侦听bounds_changed事件然后设置新的缩放&#34;方法对我来说不可靠。我认为在地图完全初始化之前我有时会调用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);
});
}
});
答案 17 :(得分:0)
对我来说,最简单的解决方案是:
map.fitBounds(bounds);
function set_zoom() {
if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);
答案 18 :(得分:0)
计算边界后,您可以检查左上角和右下角之间的距离;那么你可以通过测试距离来理解缩放级别(如果距离太远,缩放级别会很低),那么你可以使用setbound方法或setZoom来选择。
答案 19 :(得分:0)
我不想建议,但如果你必须尝试 - 先致电
gmap.fitBounds(bounds);
然后创建一个新的Thread / AsyncTask,让它休眠20-50ms左右,然后调用
gmap.setZoom( Math.max(6, gmap.getZoom()) );
(对AsyncTask使用处理程序或onPostExecute
方法)。
我不知道它是否有效,只是一个建议。除此之外,您必须以某种方式自己计算点数的缩放级别,检查它是否太低,更正它然后只需拨打gmap.setZoom(correctedZoom)
答案 20 :(得分: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);
}
如果这对你有帮助。
一切顺利
答案 21 :(得分:-1)
google.maps.event.addListener(marker, 'dblclick', function () {
var oldZoom = map.getZoom();
map.setCenter(this.getPosition());
map.setZoom(parseInt(oldZoom) + 1);
});
答案 22 :(得分:-3)
我所做的就是:
map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
它适用于V3 API。