Javascript Google Maps v3 - 限制可视区域和缩放级别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3818016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:16:20  来源:igfitidea点击:

Google Maps v3 - limit viewable area and zoom level

javascriptgoogle-mapsgoogle-maps-api-3

提问by Tomik

is it possible to limit Google map v3 to a certain area? I want to allow displaying only some area (e.g. a country) and disallow the user to slide elsewhere. Also I want to restrict the zoom level - e.g. only between levels 6 and 9. And I want to use all the base map types.

是否可以将谷歌地图 v3 限制在某个区域?我想只允许显示某些区域(例如一个国家/地区)并禁止用户在其他地方滑动。我还想限制缩放级别 - 例如,仅在级别 6 和 9 之间。我想使用所有基本地图类型。

Is there any way to achieve this?

有没有办法实现这一目标?

I had a partial success with limiting zoom level by using StyledMap, but I succeeded only with restricting ROADMAP, I wasn't able to limit zoom on other basic types this way.

我通过使用 StyledMap 限制缩放级别取得了部分成功,但我仅通过限制 ROADMAP 成功,我无法以这种方式限制其他基本类型的缩放。

Thanks for any help

谢谢你的帮助

回答by ChrisV

Better way to restrict zoom level might be to use the minZoom/maxZoomoptions rather than reacting to events?

限制缩放级别的更好方法可能是使用minZoom/maxZoom选项而不是对事件做出反应?

var opt = { minZoom: 6, maxZoom: 9 };
map.setOptions(opt);

Or the options can be specified during map initialization, e.g.:

或者可以在地图初始化期间指定选项,例如:

var map = new google.maps.Map(document.getElementById('map-canvas'), opt);

See: Google Maps JavaScript API V3 Reference

请参阅:Google Maps JavaScript API V3 参考

回答by Daniel Vassallo

You can listen to the dragendevent, and if the map is dragged outside the allowed bounds, move it back inside. You can define your allowed bounds in a LatLngBoundsobject and then use the contains()method to check if the new lat/lng center is within the bounds.

您可以收听该dragend事件,如果地图被拖到允许范围之外,请将其移回内部。您可以在LatLngBounds对象中定义允许的边界,然后使用该contains()方法检查新的经纬度中心是否在边界内。

You can also limit the zoom level very easily.

您还可以非常轻松地限制缩放级别。

Consider the following example: Fiddle Demo

考虑以下示例: Fiddle Demo

<!DOCTYPE html>
<html> 
<head> 
   <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
   <title>Google Maps JavaScript API v3 Example: Limit Panning and Zoom</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"> 

   // This is the minimum zoom level that we'll allow
   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 strictBounds = 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 (strictBounds.contains(map.getCenter())) return;

     // We're out of bounds - Move the map back within the bounds

     var c = map.getCenter(),
         x = c.lng(),
         y = c.lat(),
         maxX = strictBounds.getNorthEast().lng(),
         maxY = strictBounds.getNorthEast().lat(),
         minX = strictBounds.getSouthWest().lng(),
         minY = strictBounds.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>

Screenshot from the above example. The user will not be able to drag further south or far east in this case:

上面例子的截图。在这种情况下,用户将无法进一步向南或向东拖动:

Google Maps JavaScript API v3 Example: Force stop map dragging

Google Maps JavaScript API v3 示例:强制停止地图拖动

回答by xomena

Good news. Starting from the version 3.35 of Maps JavaScript API, that was launched on February 14, 2019, you can use new restrictionoption in order to limit the viewport of the map.

好消息。从 2019 年 2 月 14 日发布的 Maps JavaScript API 3.35 版本开始,您可以使用新restriction选项来限制地图的视口。

According to the documentation

根据文档

MapRestriction interface

A restriction that can be applied to the Map. The map's viewport will not exceed these restrictions.

MapRestriction 接口

可以应用于地图的限制。地图的视口不会超出这些限制。

source: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

来源:https: //developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

So, now you just add restriction option during a map initialization and that it. Have a look at the following example that limits viewport to Switzerland

因此,现在您只需在地图初始化期间添加限制选项即可。看看下面的例子,将视口限制在瑞士

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 46.818188, lng: 8.227512},
    minZoom: 7,
    maxZoom: 14,
    zoom: 7,
    restriction: {
      latLngBounds: {
        east: 10.49234,
        north: 47.808455,
        south: 45.81792,
        west: 5.95608
      },
      strictBounds: true
    },
  });
}
#map {
  height: 100%;
}
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap" async defer></script>

I hope this helps!

我希望这有帮助!

回答by DEEP-SILVER

To limit the zoom on v.3+. in your map setting add default zoom level and minZoom or maxZoom (or both if required) zoom levels are 0 to 19. You must declare deafult zoom level if limitation is required. all are case sensitive!

限制 v.3+ 的缩放。在您的地图设置中添加默认缩放级别和 minZoom 或 maxZoom(或两者,如果需要)缩放级别为 0 到 19。如果需要限制,您必须声明默认缩放级别。都是区分大小写的!

function initialize() {
   var mapOptions = {
      maxZoom:17,
      minZoom:15,
      zoom:15,
      ....

回答by Pat

Much better way to limit the range... used the contains logic from above poster.

限制范围的更好方法......使用了上面海报中的包含逻辑。

var dragStartCenter;

google.maps.event.addListener(map, 'dragstart', function(){
                                       dragStartCenter = map.getCenter();
                                         });

google.maps.event.addListener(this.googleMap, 'dragend', function(){
                            if (mapBounds.contains(map.getCenter())) return;
                    map.setCenter(this.dragStart);
                           });

回答by Jonathan Busuttil

This can be used to re-center the map to a specific location. Which is what I needed.

这可用于将地图重新​​居中到特定位置。这正是我所需要的。

    var MapBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(35.676263, 13.949096),
    new google.maps.LatLng(36.204391, 14.89038));

    google.maps.event.addListener(GoogleMap, 'dragend', function ()
    {
        if (MapBounds.contains(GoogleMap.getCenter()))
        {
            return;
        }
        else
        {
            GoogleMap.setCenter(new google.maps.LatLng(35.920242, 14.428825));
        }
    });

回答by Anup

myOptions = {
        center: myLatlng,
        minZoom: 6,
        maxZoom: 9,
        styles: customStyles,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

回答by Matej P.

As of middle 2016, there is no official way to restrict viewable area. Most of ad-hoc solutions to restrict the bounds have a flaw though, because they don't restrict the bounds exactly to fit the map view, they only restrict it if the center of the map is out of the specified bounds. If you want to restrict the bounds to overlaying image like me, this can result in a behavior like illustrated below, where the underlaying map is visible under our image overlay:

截至 2016 年年中,没有官方方法来限制可视区域。但是,大多数限制边界的临时解决方案都有一个缺陷,因为它们并没有完全限制边界以适合地图视图,它们仅在地图中心超出指定边界时才对其进行限制。如果你想像我一样限制覆盖图像的边界,这可能会导致如下图所示的行为,其中底图在我们的图像覆盖下可见:

enter image description here

在此处输入图片说明

To tackle this issue, I have created a library, which successfully restrict the bounds so you cannot pan out of the overlay.

为了解决这个问题,我创建了一个library,它成功地限制了边界,所以你不能平移覆盖。

However, as other existing solutions, it has a "vibrating" issue. When the user pans the map aggressively enough, after they release the left mouse button, the map still continues panning by itself, gradually slowing. I always return the map back to the bounds, but that results in kind of vibrating. This panning effect cannot be stopped with any means provided by the Js API at the moment. It seems that until google adds support for something like map.stopPanningAnimation() we won't be able to create a smooth experience.

但是,与其他现有解决方案一样,它存在“振动”问题。当用户足够积极地平移地图时,释放鼠标左键后,地图仍会继续自行平移,逐渐变慢。我总是将地图返回到边界,但这会导致某种振动。目前 Js API 提供的任何方法都无法阻止这种平移效果。似乎在谷歌添加对 map.stopPanningAnimation() 之类的支持之前,我们将无法创建流畅的体验。

Example using the mentioned library, the smoothest strict bounds experience I was able to get:

使用上述库的示例,我能够获得的最流畅的严格边界体验:

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/full/images/talkeetna.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:400px; width:500px;"></div>
     <script  type="text/javascript"src="https://raw.githubusercontent.com/matej-pavla/StrictBoundsImage/master/StrictBoundsImage.js"></script>
</body>

The library is also able to calculate the minimum zoom restriction automatically. It then restricts the zoom level using minZoommap's attribute.

该库还能够自动计算最小缩放限制。然后它使用minZoom地图的属性限制缩放级别。

Hopefully this helps someone who wants a solution which fully respect the given boundaries and doesn't want to allow panning out of them.

希望这可以帮助那些想要一个完全尊重给定边界并且不想允许平移的解决方案的人。

回答by Alexander Palamarchuk

Here's my variant to solve the problem of viewable area's limitation.

这是我解决可视区域限制问题的变体。

        google.maps.event.addListener(this.map, 'idle', function() {
            var minLat = strictBounds.getSouthWest().lat();
            var minLon = strictBounds.getSouthWest().lng();
            var maxLat = strictBounds.getNorthEast().lat();
            var maxLon = strictBounds.getNorthEast().lng();
            var cBounds  = self.map.getBounds();
            var cMinLat = cBounds.getSouthWest().lat();
            var cMinLon = cBounds.getSouthWest().lng();
            var cMaxLat = cBounds.getNorthEast().lat();
            var cMaxLon = cBounds.getNorthEast().lng();
            var centerLat = self.map.getCenter().lat();
            var centerLon = self.map.getCenter().lng();

            if((cMaxLat - cMinLat > maxLat - minLat) || (cMaxLon - cMinLon > maxLon - minLon))
            {   //We can't position the canvas to strict borders with a current zoom level
                self.map.setZoomLevel(self.map.getZoomLevel()+1);
                return;
            }
            if(cMinLat < minLat)
                var newCenterLat = minLat + ((cMaxLat-cMinLat) / 2);
            else if(cMaxLat > maxLat)
                var newCenterLat = maxLat - ((cMaxLat-cMinLat) / 2);
            else
                var newCenterLat = centerLat;
            if(cMinLon < minLon)
                var newCenterLon = minLon + ((cMaxLon-cMinLon) / 2);
            else if(cMaxLon > maxLon)
                var newCenterLon = maxLon - ((cMaxLon-cMinLon) / 2);
            else
                var newCenterLon = centerLon;

            if(newCenterLat != centerLat || newCenterLon != centerLon)
                self.map.setCenter(new google.maps.LatLng(newCenterLat, newCenterLon));
        });

strictBoundsis an object of new google.maps.LatLngBounds()type. self.gmapstores a Google Map object (new google.maps.Map()).

strictBounds是一个new google.maps.LatLngBounds()类型的对象。self.gmap存储一个 Google Map 对象 ( new google.maps.Map())。

It really works but don't only forget to take into account the haemorrhoids with crossing 0th meridians and parallels if your bounds cover them.

它确实有效,但如果您的界限覆盖它们,请不要忘记考虑跨越第 0 经络和平行线的痔疮。

回答by Mayko

For some reason

因为某些原因

if (strictBounds.contains(map.getCenter())) return;

didnt work for me (maybe a southern hemisphere issue). I had to change it to:

对我不起作用(可能是南半球问题)。我不得不将其更改为:

    function checkBounds() {
        var c = map.getCenter(),
            x = c.lng(),
            y = c.lat(),
            maxX = strictBounds.getNorthEast().lng(),
            maxY = strictBounds.getNorthEast().lat(),
            minX = strictBounds.getSouthWest().lng(),
            minY = strictBounds.getSouthWest().lat();

        if(x < minX || x > maxX || y < minY || y > maxY) {
            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));
        }
    }

Hope it will help someone.

希望它会帮助某人。