我有一组点,我想在嵌入式谷歌地图(API v3)上绘制。我希望边界容纳所有的点,除非缩放级别太低(即,缩小太多)。我的方法是这样的:
var bounds = new google.maps.LatLngBounds();
// extend bounds with each point
gmap.fitBounds(bounds);
gmap.setZoom( Math.max(6, gmap.getZoom()) );
这行不通。最后一行“gmap.setZoom()”如果在fitBounds之后直接调用,则不会改变地图的缩放级别。
有没有一种方法来获得缩放级别的边界而不应用到地图?还有其他解决方法吗?
在这个函数中,您只需要动态添加元数据来存储几何类型,因为该函数接受任何几何。
“fitGeometries”是一个扩展映射对象的JSON函数。
"geometries"是一个通用的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);
},
我用这个来确保缩放级别不超过设置的级别,这样我就知道卫星图像是可用的。
向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);
如果我没记错的话,我假设你想让你的所有点在地图上以最高的缩放级别可见。我通过将地图的缩放级别初始化为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);
结果:
成功!
我有同样的问题,我能够解决它使用下面的代码。这个监听器(google.maps.addListenerOnce())事件只会在map.fitBounds()执行之后被触发一次。所以,没有必要
跟踪并手动删除侦听器,或者
等待地图空闲。
它最初设置适当的缩放级别,并允许用户放大和缩小超过初始缩放级别,因为事件侦听器已经过期。例如,如果只调用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)
}
});
像我一样,如果你不愿意和听众一起玩,这是我想出的一个简单的解决方案:
在地图上添加一个方法,严格按照你的要求工作,像这样:
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)来覆盖缩放范围..
我看到许多不正确或太复杂的解决方案,所以决定张贴一个工作,优雅的解决方案。
setZoom()没有像你期望的那样工作的原因是fitBounds()是异步的,所以它不能保证它会立即更新缩放,但是你对setZoom()的调用依赖于这一点。
你可能会考虑在调用fitBounds()之前设置minZoom map选项,然后在调用完成后清除它(这样用户仍然可以手动缩小):
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文档。
为了配合另一个解决方案-我发现“监听bounds_changed事件,然后设置新的缩放”方法对我来说并不可靠。我认为我有时在地图已经完全初始化之前调用fitBounds,初始化导致一个bounds_changed事件,将使用侦听器,在fitBounds改变边界和缩放级别之前。我最终得到了这段代码,到目前为止似乎还可以工作:
// 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);
});
}
});