5

In an application I'm building, the Google Maps API takes up most (if not all) of the screen. However, during testing I've discovered that a user can drag the map down far enough so that the map isn't displayed anymore, and all thats left is a grey background.

How can I stop this? I have set a minZoom but this only solves the problem for when the page is loaded and the user wants to zoom out.

mickburkejnr
  • 3,652
  • 12
  • 76
  • 109

4 Answers4

17

new solution

new google.maps.Map(document.getElementById('map'), {
restriction: {
    latLngBounds: {
        north: 85,
        south: -85,
        west: -180,
        east: 180
    }
},
});
Nazik
  • 8,696
  • 27
  • 77
  • 123
Felipe Fetzner
  • 206
  • 2
  • 4
8

You can examine the map's bounds and see and if the user has panned outside of the expected range, then disable panning and return to the map area.

map.getBounds().getSouthWest().lat() must be > -85

map.getBounds().getNorthEast().lat() must be < 85

So, for example:

  G.event.addListener(map, 'drag', checkLatitude);

and then

function checkLatitude(){
    var proj = map.getProjection();
    var bounds = map.getBounds();
    var sLat = map.getBounds().getSouthWest().lat();
    var nLat = map.getBounds().getNorthEast().lat();
    if (sLat < -85 || nLat > 85) {
//gray areas are visible
         alert('Gray area visible');
         map.setOptions({draggable:false});
  //return to a valid position
    }

}

The limit values of -85 and 85 are only approximate. The exact value is atan(sinh(PI)) *180 / PI = 85.05112878..(explained in this post in the old forum).

Marcelo
  • 9,387
  • 3
  • 35
  • 40
3

This solution is based on Marcelo's very good answer, however his solution will completely disable any further dragging (including valid dragging of the visible area of the map), once the map goes beyond the world's maximum or minimum latitude. Here's a clarified version, that will pull the map back into view if the user has exceeded the maximum or minimum latitude by dragging. It will still allow the user to drag for all visible areas.

Also, this solution sets a minimum zoom level for the map, which can be used to to ensure that attempted zooming doesn't cause the map to display grey areas.

(see also How do I limit panning in Google maps API V3?)

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

(I didn't use the 'center_changed' listener. The center_changed event fires continuously while the map is being panned, which potentially can prevent the user from ever panning to a grey area, instead of 'snapping back'. This can cause stackoverflow errors in Chrome though, because of the number of times the event will be triggered)

Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
-1

I am having the same problem as you. One way I got around it is by putting this where you initialise the map:

            google.maps.event.trigger(map, 'resize');
            map.setZoom( map.getZoom() );

            google.maps.event.addListener(map, "idle", function(){
                google.maps.event.trigger(map, 'resize');
            }); 

This basically means when you drag the map and it "settles", the event is fired which resizes it and consequently means the map is shown for some reason.

If you figured a non hacky way them please share. :)

JamesG
  • 2,018
  • 2
  • 28
  • 57