如何限制谷歌地图API V3中的平移?

在V2中,有一种限制平移/拖动的方法,所以地图保持在一定范围内。 在V3中如何做到这一点?

比方说,我希望用户只看欧洲。 我已经限制了缩放,但是如果我允许拖动(在这种情况下,我必须出于其他原因),那么用户可以平移到我想要显示的区域之外。

请给出工作示例或代码片段 – 我不是专家编码器…

谢谢!

我想我晚了一点,但是因为这正是我刚才所需要的,而且我对它进行了改进,所以我想我会回答一个问题。

通过Daniel Vassallo和brendo的回答,用户仍然可以使用pan控制(如果已激活)从想要的区域移开。 @ Yauhen.F的事情在评论中提到。

所以不是使用dragend事件,而是使用center_changed事件。 在拖动过程中以及每次使用平移控制时都会持续触发。

// bounds of the desired area var allowedBounds = new google.maps.LatLngBounds( new google.maps.LatLng(70.33956792419954, 178.01171875), new google.maps.LatLng(83.86483689701898, -88.033203125) ); var lastValidCenter = map.getCenter(); google.maps.event.addListener(map, 'center_changed', function() { if (allowedBounds.contains(map.getCenter())) { // still within valid bounds, so save the last valid position lastValidCenter = map.getCenter(); return; } // not valid anymore => return to last valid position map.panTo(lastValidCenter); }); 

通过在拖动过程中连续保存最后一个有效位置,一旦超出界限,运动就会停止,而不是在拖动结束后反向运动。 ……

诀窍是听dragend事件,如果地图被拖动到允许的范围之外,将其移回到里面。 如果将允许的边界定义为LatLngBounds对象,则可以使用contains()方法,因为如果给定的lat / lng参数在边界内,则返回true。

限制缩放级别也很重要,但看起来你已经在做这个了。

因此,您可能想要尝试下面的示例:

 <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <title>Google Maps JavaScript API v3 Example: Limit Panning</title> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> </head> <body> <div id="map" style="width: 400px; height: 300px;"></div> <script type="text/javascript"> var minZoomLevel = 5; var map = new google.maps.Map(document.getElementById('map'), { zoom: minZoomLevel, center: new google.maps.LatLng(38.50, -90.50), mapTypeId: google.maps.MapTypeId.ROADMAP }); // Bounds for North America var allowedBounds = new google.maps.LatLngBounds( new google.maps.LatLng(28.70, -127.50), new google.maps.LatLng(48.85, -55.90)); // Listen for the dragend event google.maps.event.addListener(map, 'dragend', function() { if (allowedBounds.contains(map.getCenter())) return; // Out of bounds - Move the map back within the bounds var c = map.getCenter(), x = c.lng(), y = c.lat(), maxX = allowedBounds.getNorthEast().lng(), maxY = allowedBounds.getNorthEast().lat(), minX = allowedBounds.getSouthWest().lng(), minY = allowedBounds.getSouthWest().lat(); if (x < minX) x = minX; if (x > maxX) x = maxX; if (y < minY) y = minY; if (y > maxY) y = maxY; map.setCenter(new google.maps.LatLng(y, x)); }); // Limit the zoom level google.maps.event.addListener(map, 'zoom_changed', function() { if (map.getZoom() < minZoomLevel) map.setZoom(minZoomLevel); }); </script> </body> </html> 

从上面的例子截图。 在这种情况下,用户将无法拖动到更远的南方或远东。

Google Maps JavaScript API v3示例:限制平移

我的版本基于@HenningJ中的版本,但是对最后一个版本中心进行了一些修改,以便沿着边界的边缘平滑拖动

 <!DOCTYPE html> <html> <head> <style type="text/css"> html { height: 100% } body { height: 100%; margin: 0; padding: 0 } #map-canvas { height: 100% } </style> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> </script> <script type="text/javascript"> function initialize() { var mapOptions = { center: new google.maps.LatLng(28.70, -127.50), zoom: 4, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); // bounds of the desired area var allowedBounds = new google.maps.LatLngBounds( new google.maps.LatLng(28.70, -127.50), new google.maps.LatLng(48.85, -55.90) ); var boundLimits = { maxLat : allowedBounds.getNorthEast().lat(), maxLng : allowedBounds.getNorthEast().lng(), minLat : allowedBounds.getSouthWest().lat(), minLng : allowedBounds.getSouthWest().lng() }; var lastValidCenter = map.getCenter(); var newLat, newLng; google.maps.event.addListener(map, 'center_changed', function() { center = map.getCenter(); if (allowedBounds.contains(center)) { // still within valid bounds, so save the last valid position lastValidCenter = map.getCenter(); return; } newLat = lastValidCenter.lat(); newLng = lastValidCenter.lng(); if(center.lng() > boundLimits.minLng && center.lng() < boundLimits.maxLng){ newLng = center.lng(); } if(center.lat() > boundLimits.minLat && center.lat() < boundLimits.maxLat){ newLat = center.lat(); } map.panTo(new google.maps.LatLng(newLat, newLng)); }); } google.maps.event.addDomListener(window, 'load', initialize); </script> </head> <body> <div id="map-canvas"/> </body> </html> 

小提琴: http : //jsfiddle.net/koenpunt/n7h6t/

这是上面的一个很好的扩展,它将通过监听dragstart事件来将Map中心重置到最后的有效位置。

 // Limit panning var lastCenter = map.getCenter(); google.maps.event.addListener(map, 'dragstart', function() { lastCenter = map.getCenter(); }); google.maps.event.addListener(map, 'dragend', function() { if(allowedBounds.contains(map.getCenter())) return; map.setCenter(lastCenter); }); 

要限制的最佳方法是设置缩放级别和中心点,并禁用缩放,滚动等控件,如下所示。

  var latlng = new google.maps.LatLng(18.283078,84.047556); var myOptions = { zoom: 12, center: latlng, zoomControl: false, mapTypeId: google.maps.MapTypeId.ROADMAP, scrollwheel: false, navigationControl: false, mapTypeControl: false, scaleControl: false, draggable: false, disableDoubleClickZoom: true, }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 

这是Tom Andersen的答案和目前接受的HenningJ答案合并的解决scheme。 这样做的好处是:1)可以更顺畅地沿着边缘滚动(HenningJ的解决scheme看起来很笨拙),2)在放大区域时没有任何问题(当放大时HenningJ的答案似乎中断了并在边界附近)。

汤姆的回答已经接近为我工作了,只是将locking区域放到了屏幕的中心,这对于我正在开发的应用程序来说是不可接受的。

 // bounds of the desired area var allowedBounds = new google.maps.LatLngBounds( new google.maps.LatLng(70.33956792419954, 178.01171875), new google.maps.LatLng(83.86483689701898, -88.033203125) ); var lastValidCenter = map.getCenter(); google.maps.event.addListener(map, 'center_changed', function() { var mapBounds = map.getBounds(); var mapNe = mapBounds.getNorthEast(); var mapSw = mapBounds.getSouthWest(); var center = map.getCenter(); if( allowedBounds.contains(mapNe) && allowedBounds.contains(mapSw) ) { //the user is scrolling within the bounds. lastValidCenter = center; return; } //the user has scrolled beyond the edge. var mapWidth = mapNe.lng() - mapSw.lng(); var mapHeight = mapNe.lat() - mapSw.lat(); var x = center.lng(); var y = center.lat(); var maxX = allowedBounds.getNorthEast().lng(); var maxY = allowedBounds.getNorthEast().lat(); var minX = allowedBounds.getSouthWest().lng(); var minY = allowedBounds.getSouthWest().lat(); //shift the min and max dimensions by 1/2 of the screen size, so the bounds remain at the edge of the screen maxX -= (mapWidth / 2); minX += (mapWidth / 2); maxY -= (mapHeight / 2); minY += (mapHeight / 2); if (x < minX) { x = minX; } if (x > maxX) { x = maxX; } if (y < minY){ y = minY; } if (y > maxY){ y = maxY; } map.panTo(new google.maps.LatLng(y, x)); }); 

我试着从HenningJ那里得到答案,地图不会停止摇摄,直到中心位于不理想的边界的一个angular落。 这是我的解决scheme:

 google.maps.event.addListener(map, 'center_changed', function() { var mapBounds = map.getBounds(); if(allowedBounds.contains(mapBounds.getNorthEast()) && allowedBounds.contains(mapBounds.getSouthWest())) { lastCenter = map.getCenter(); return; } map.panTo(lastCenter); }, this)); 

我会张贴我的答案,以防万一有人感兴趣,因为我无法达到我需要的任何其他解决scheme张贴在这里。

我所需要的是限制地图的垂直边界(纬度),这样用户就不能跨越地球的纬度范围(+/- 85度),但是任何其他边界都可以工作。

这种方法使用与其他地方所描述的相同的center_changed事件,并简单地修复了中心,以防止被禁止边界的部分被显示。

这种机制只有在设置了地图的最小缩放比例的情况下才能起作用,从而放大的图像不能显示比允许范围内更多的区域。

工作示例: http : //jsbin.com/vizihe

 function initMap() { // sample bounds, can be anything and goes hand in hand with minZoom var northBoundary = 40 var southBoundary = -40 var map = new google.maps.Map(document.getElementById('map'), { center: {lat: 0, lng: 0}, zoom: 4, // it's important to set this to a large enough value // so that zooming out does not show an area larger than allowed minZoom: 4 }) map.addListener('center_changed', function () { var bounds = map.getBounds(); var ne = bounds.getNorthEast() var sw = bounds.getSouthWest() var center = map.getCenter() if(ne.lat() > northBoundary) { map.setCenter({lat: center.lat() - (ne.lat() - northBoundary), lng: center.lng()}) } if(sw.lat() < southBoundary) { map.setCenter({lat: center.lat() - (sw.lat() - southBoundary), lng: center.lng()}) } }) } 
 html, body, #map { height: 100%; margin: 0; padding: 0; } 
 <!DOCTYPE html> <html> <head> <meta name="description" content="limit google map panning"> <title>Simple Map</title> <meta name="viewport" content="initial-scale=1.0"> <meta charset="utf-8"> </head> <body> <div id="map"></div> <script src="https://maps.googleapis.com/maps/api/js?callback=initMap" async defer></script> </body> </html> 

关于这个问题还有另外一个线索也很好。 我不得不解决的问题是,而不是手动设置边界和检查中心的遏制,我想在页面加载设置边界,然后允许拖放到边缘,如果放大。

所以我在地图加载上设置了一次平移边界。 然后我检查地图是否仍然在最大变焦位置,如果是,返回最初的中心位置。 如果放大,我想平移到初始边界的边缘,而不是只检查是否包含CENTER,因为这会将允许的平移延伸一半的视口。

不幸的是,虽然这样做可以让工作顺利进行,并且在缓慢的时候工作得很好,但是如果你能够快速平稳地进行工作,那么这个工作会有点不顺利

如果你有什么build议可以避免,我会很感激。

  map = new google.maps.Map( // defaults document.getElementById("map22"), { disableDefaultUI : true, zoomControl : true, zoom : 7, minZoom : 7, maxZoom : 10, center : new google.maps.LatLng( 64.99473104134819, -19.22332763671875 ), mapTypeId : google.maps.MapTypeId.ROADMAP } ); function borders(){ return { maxLat : map.getBounds().getNorthEast().lat(), maxLng : map.getBounds().getNorthEast().lng(), minLat : map.getBounds().getSouthWest().lat(), minLng : map.getBounds().getSouthWest().lng(), center : map.getCenter() } } google.maps.event.addListenerOnce(map,'idle',function() { limit = borders(); }); google.maps.event.addListener(map,'drag',function() { if(map.getZoom() == 7) return map.setCenter(limit.center); current = borders(); if( current.maxLng < limit.maxLng && current.minLng > limit.minLng ) activeCenterLng = current.center.lng(); if( current.maxLat < limit.maxLat && current.minLat > limit.minLat ) activeCenterLat = current.center.lat(); map.setCenter( new google.maps.LatLng( activeCenterLat, activeCenterLng ) ); }); 

当我使用drag或dragend或者其他的东西时,地图会跳回到允许的范围内,而不是简单地限制溢出的移动。 只要把这个事件改成'center_changed'就可以阻止它像这样跳跃。

修改jsfiddle: http : //jsfiddle.net/Vjdde/1/

编辑:不知道为什么小提琴不会产生堆栈溢出,但它应该,因为setCenter将再次调用center_changed ..只是小心

这里的解决scheme给我留下了两个问题。 首先,如果按住方向键开始快速移动,当它碰到边缘的时候,它不会一直走到边缘,因为由于平移加速需要很大的“步数”,所以下一个“一步“将超出界限,所以它不会采取最后的”步骤“。 所以一旦停止,你可以释放箭头键,然后再按一次,它会进一步泛。 其次,这些解决scheme没有正确地包含变焦后的平移。 我设法解决了这两个问题,并在另一个线程中发布了我的解决scheme,但是我想我会把它链接到这里,因为这是首先让我以正确的方向开始的线程。

这是HenningJ – 但是iN上的HenningJ使用lastValidCentre – 这是不好的,因为它的老,所以我夹,这使得它在iOS上更好。

 var mapObject = plugin_map.gmap3('get'); var allowedBounds = new google.maps.LatLngBounds( new google.maps.LatLng(41.3957556, -88.4345472), new google.maps.LatLng(49.4010417, -78.4286389) ); google.maps.event.addListener(mapObject, 'center_changed', function() { if (allowedBounds.contains(mapObject.getCenter())) { // still within valid bounds, so save the last valid position return; } // not valid anymore => return to last valid position var c = mapObject.getCenter(), x = c.lng(), y = c.lat(), maxX = allowedBounds.getNorthEast().lng(), maxY = allowedBounds.getNorthEast().lat(), minX = allowedBounds.getSouthWest().lng(), minY = allowedBounds.getSouthWest().lat(); if (x < minX) x = minX; if (x > maxX) x = maxX; if (y < minY) y = minY; if (y > maxY) y = maxY; //mapObject.setCenter(new google.maps.LatLng(y, x)); mapObject.panTo(new google.maps.LatLng(y, x)); }); 

我知道我对这个晚会有点迟到,但是从2016年中旬开始 ,似乎没有官方限制可视区域的方法。

有一些解决scheme来限制边界(其中一些在这个问题中),但对我来说他们有一个缺陷,因为他们没有严格限制边界以适应地图视图,他们只限制地图中心被包含在指定范围。 如果你想限制像我这样覆盖图像的边界,这可能会导致如下图所示的行为,其中下面的地图在我们的图像覆盖图下可见:

在这里输入图像描述

为了解决这个问题,我创build了一个库 ,它成功地限制了边界,所以你不能从覆盖层中移出。

但是,作为其他现有的解决scheme,它有一个“振动”的问题。 当用户足够积极地平移地图时,在释放鼠标左键之后,地图仍然继续自行平移,逐渐放缓。 我总是把地图返回到边界,但是这样会导致一些振动,一段时间后就结束了。 这个平移效果目前无法用Js API提供的任何方式来停止。 看来,直到谷歌增加了像map.stopPanningAnimation()的支持,我们将无法创造一个平稳的体验。

使用提到的库的例子,我能够得到最平滑的边界体验:

 function initialise(){ var myOptions = { zoom: 5, center: new google.maps.LatLng(0,0), mapTypeId: google.maps.MapTypeId.ROADMAP, }; var map = new google.maps.Map(document.getElementById('map'), myOptions); addStrictBoundsImage(map); } function addStrictBoundsImage(map){ var bounds = new google.maps.LatLngBounds( new google.maps.LatLng(62.281819, -150.287132), new google.maps.LatLng(62.400471, -150.005608)); var image_src = 'https://developers.google.com/maps/documentation/' + 'javascript/examples/fullhttp://img.dovov.comtalkeetna.png'; var strict_bounds_image = new StrictBoundsImage(bounds, image_src, map); } 
 <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("maps", "3",{other_params:"sensor=false"}); </script> <body style="margin:0px; padding:0px;" onload="initialise()"> <div id="map" style="height:500px; width:1000px;"></div> <script type="text/javascript"src="https://raw.githubusercontent.com/matej-pavla/StrictBoundsImage/master/StrictBoundsImage.js"></script> </body> 

这是一个简单的解决scheme,可以在手机和桌面上使用。 它将停止超出世界最大或最小纬度的地图平移,并允许设置最小缩放级别,这可以帮助防止通过缩小太远(取决于您为地图设置的大小)灰度区域变得可见:

(我build议使用center_changed事件,正如HenningJ接受的答案中所build议的那样。在我的例子中,这个事件的数量在Google Chrome中导致堆栈溢出错误,相反,可以使用“dragend”事件 – 虽然这样会允许用户拖到区域之外,然后立即“跳回”到地图的有效区域)。

 var lastValidCenter; var minZoomLevel = 2; setOutOfBoundsListener(); function setOutOfBoundsListener() { google.maps.event.addListener(map, 'dragend', function () { checkLatitude(map); }); google.maps.event.addListener(map, 'idle', function () { checkLatitude(map); }); google.maps.event.addListener(map, 'zoom_changed', function () { checkLatitude(map); }); }; function checkLatitude(map) { if (this.minZoomLevel) { if (map.getZoom() < minZoomLevel) { map.setZoom(parseInt(minZoomLevel)); } } var bounds = map.getBounds(); var sLat = map.getBounds().getSouthWest().lat(); var nLat = map.getBounds().getNorthEast().lat(); if (sLat < -85 || nLat > 85) { //the map has gone beyone the world's max or min latitude - gray areas are visible //return to a valid position if (this.lastValidCenter) { map.setCenter(this.lastValidCenter); } } else { this.lastValidCenter = map.getCenter(); } }