views:

176

answers:

3

Hello !

I am working with Google Maps right now and I want to be able to disallow user dragging map out of specified boundaries.

var strictBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(49.00, 14.07),
    new google.maps.LatLng(54.50, 24.09)
);

What should I do ? I tried to use drag event but with no luck..

google.maps.event.addListener(map, 'drag', function() {
    if (
         !strictBounds.contains(map.getBounds().getNorthEast())
      || !strictBounds.contains(map.getBounds().getSouthWest())
    ) {
        // map is out of bounds here
    }
});

How to stop user's drag on strictBounds ?

A: 

Try this:

var strictBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(49.00, 14.07),
    new google.maps.LatLng(54.50, 24.09)
);

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

    if (!strictBounds.intersects(map.getBounds()) ) {
        // map is out of bounds here
        map.setCenter(strictBounds.getCenter()); 
    }
});

Its not quite ideal in that its just moving the map centre back to the strictBounds centre, Ideally you'd try and calculate the nearest edge of the bounds that they tried to drag past. Its also somewhat slow to catch that they have dragged outside the bounds but that's an issue with the API

RueTheWhirled
I tried `setCenter` already but it causes not smooth moving if user do not end to drag the map.
hsz
A: 

You may want to listen to the dragend event instead, and if the map is dragged outside the allowed bounds, move it back inside. It's good that you are using a LatLngBounds object to define your bounds, because you will be able to use the contains() method, which returns true if the given lat/lng argument is within the bounds.

You should probably also limit the zoom level, because by zooming out the user would still be able to "see" the map outside the bounds.

Therefore, you may want to try the following example:

<!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"&gt;&lt;/script&gt;
</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 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;

     // 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 east in this case:

Google Maps JavaScript API v3 Example: Force stop map dragging

Daniel Vassallo
Thanks for the answer. I've noticed that way before (but without calculations). However it will still allow user to see other parts of map if he will drag much more. I am looking for a way that will break user's drag in the same moment when he will try to access disallowed area of the map.
hsz
@hsz: In that case, you might want to listen for the `drag` event instead of the `dragend`, but the blocking won't look very nice. You might also prefer using `panTo` instead of `setCenter`.
Daniel Vassallo
A: 

This works, although it's a bit jumpy:

//  Boundaries
var southBound = 33;
var westBound = -119;
var northBound = 34;
var eastBound = -118;

// Intersect boxes for stopping drag
var topBox = new google.maps.LatLngBounds(
    new google.maps.LatLng(northBound, westBound),
    new google.maps.LatLng(northBound + 1, eastBound)
);
var rightBox = new google.maps.LatLngBounds(
    new google.maps.LatLng(southBound, eastBound),
    new google.maps.LatLng(northBound, eastBound + 1)
);
var bottomBox = new google.maps.LatLngBounds(
    new google.maps.LatLng(southBound - 1, westBound),
    new google.maps.LatLng(southBound, eastBound)
);
var leftBox = new google.maps.LatLngBounds(
    new google.maps.LatLng(southBound, westBound - 1),
    new google.maps.LatLng(northBound, westBound)
);

// Last known good center point
var lastGoodCenter = map.getCenter();

// Listen for dragging  
google.maps.event.addListener(map, 'drag', function() {
    // If the map's bounds intersect with one of the stop boxes
    if (map.getBounds().intersects(topBox) || map.getBounds().intersects(rightBox) 
        || map.getBounds().intersects(bottomBox) || map.getBounds().intersects(leftBox)){
        // Go back to the good center
        map.setCenter(lastGoodCenter);
    }else{
        // Or set this new center as good
        lastGoodCenter = map.getCenter();
    }
});
eecue
Using panTo instead of setCenter is smoother, but then shows part of the map you don't want to show. =]
eecue