Google Maps v3 - limit viewable area and zoom level

JavascriptGoogle MapsGoogle Maps-Api-3

Javascript Problem Overview


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.

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.

Thanks for any help

Javascript Solutions


Solution 1 - Javascript

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

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

Solution 2 - Javascript

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

You can also limit the zoom level very easily.

Consider the following example: 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

Solution 3 - Javascript

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

According to the documentation

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

source: 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!

Solution 4 - Javascript

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!

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

Solution 5 - Javascript

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);
                           });

Solution 6 - Javascript

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));
        }
    });

Solution 7 - Javascript

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

Solution 8 - Javascript

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));
		});

strictBounds is an object of new google.maps.LatLngBounds() type. self.gmap stores a Google Map object (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.

Solution 9 - Javascript

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.

Solution 10 - Javascript

One solution is like, If you know the specific lat/lng.

google.maps.event.addListener(map, 'idle', function() {

	map.setCenter(new google.maps.LatLng(latitude, longitude));
	map.setZoom(8);

});

If don't have specific lat/lng

google.maps.event.addListener(map, 'idle', function() {
	
	map.setCenter(map.getCenter());
	map.setZoom(8);

});

or

google.maps.event.addListener(map, 'idle', function() {
	
	var bounds = new google.maps.LatLngBounds();
	map.setCenter(bounds.getCenter());
	map.setZoom(8);

});

Solution 11 - Javascript

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:

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.

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.

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 minZoom map's attribute.

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

Solution 12 - Javascript

This may be helpful.

  var myOptions = {
      center: new google.maps.LatLng($lat,$lang),
      zoom: 7,
      disableDefaultUI: true,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

The Zoom level can be customizable according to the requirement.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomikView Question on Stackoverflow
Solution 1 - JavascriptChrisVView Answer on Stackoverflow
Solution 2 - JavascriptDaniel VassalloView Answer on Stackoverflow
Solution 3 - JavascriptxomenaView Answer on Stackoverflow
Solution 4 - JavascriptDEEP-SILVERView Answer on Stackoverflow
Solution 5 - JavascriptPatView Answer on Stackoverflow
Solution 6 - JavascriptJonathan BusuttilView Answer on Stackoverflow
Solution 7 - JavascriptAnupView Answer on Stackoverflow
Solution 8 - JavascriptAlexander PalamarchukView Answer on Stackoverflow
Solution 9 - JavascriptMaykoView Answer on Stackoverflow
Solution 10 - JavascriptJaison JamesView Answer on Stackoverflow
Solution 11 - JavascriptMatej P.View Answer on Stackoverflow
Solution 12 - JavascriptSamir DashView Answer on Stackoverflow