Google Maps API V3 fitbounds() zooms out but never in

26,971

Solution 1

Nothing fancy needed here. First fit bounds then pan to it. This will give you the proper zoom and contain the entire bounds.

map.fitBounds(bounds);
map.panToBounds(bounds);

Solution 2

The problem is this: we set

var bounds = new google.maps.LatLngBounds();

so that we can later fit our markers to a bounded area on the map. GMaps will always zoom out asynchronously to fitBounds() accordingly, but will not zoom in to achieve the same (as previously noted by @broady). This is not ideal for many applications as once you have gone and displayed a series of markers on the map that caused the map to zoom out (maybe <10), it will not zoom back in without the user manually doing so.

GMaps will continue to use the bounds of the (lack of better words) most zoomed out marker collection status (sorry). Setting to 'null' before each call for new markers gives you a fresh map to work with.

To auto-zoom in, simply set the LatLngBounds(); to 'null' like so (see pseudo example below to see its placement):

bounds = new google.maps.LatLngBounds(null);

Pseudo example:

// map stuff/initiation
...

var bounds = new google.maps.LatLngBounds();
var gmarkers = [];

function CreateMarker (obj) {
    myLatLng = new google.maps.LatLng(obj['latitude'], obj['longitude']);
    marker = new google.maps.Marker({
        position: myLatLng,
        map: map
    });
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
            infowindow.setContent(obj['job']);
            infowindow.open(map, marker);
        }
    })(marker, i));
    bounds.extend(myLatLng);
    gmarkers.push(marker);
}

....

// here's an AJAX method I use to grab marker coords from a database:

$.ajax({
    beforeSend: function() {
        clear_markers(gmarkers); // see below for clear_markers() function declaration
    },
    cache: false,
    data: params,
    dataType: 'json',
    timeout: 0,
    type: 'POST',
    url: '/map/get_markers.php?_=<?php echo md5(session_id() . time() . mt_rand(1,9999)); ?>',
    success: function(data) {
        if (data) {
            if (data['count'] > 0) {
                var obj;
                var results = data['results'];

                // Plot the markers
                for (r in results) {
                    if (r < (data['count'])) {
                        CreateMarker(results[r]);
                    }
                }
            }
        }
    },
    complete: function() {
        map.fitBounds(bounds);
    }
});

// clear_markers()
function clear_markers(a) {
    if (a) {
        for (i in a) {
            a[i].setMap(null);
        }
        a.length = 0;
    }
    bounds = new google.maps.LatLngBounds(null); // this is where the magic happens; setting LatLngBounds to null resets the current bounds and allows the new call for zoom in/out to be made directly against the latest markers to be plotted on the map
}

Solution 3

That's right, fitBounds only ensures that the provided bounds are visible. It doesn't zoom in to an appropriate level.

You could first call setZoom(20), then fitBounds.

Solution 4

What helped me was using 0 padding as the second parameter to fitBounds(bounds, padding), here is the full code sample:

function initMap() {
    var mapOptions = {
        center: new google.maps.LatLng(0, 0),
        zoom: 1,
        minZoom: 1
    };
    map = new google.maps.Map(document.getElementById('officeMap'), mapOptions);
    google.maps.event.addListenerOnce(map, 'idle', function() {
        //Map is ready
        worldViewFit(map);
    });
}
function worldViewFit(mapObj) {
    var worldBounds = new google.maps.LatLngBounds(
        new google.maps.LatLng(70.4043,-143.5291),  //Top-left
        new google.maps.LatLng(-46.11251, 163.4288)  //Bottom-right
    );
    mapObj.fitBounds(worldBounds, 0);
    var actualBounds = mapObj.getBounds();
    if(actualBounds.getSouthWest().lng() == -180 && actualBounds.getNorthEast().lng() == 180) {
        mapObj.setZoom(mapObj.getZoom()+1);
    }
}

Solution 5

Hmm, interesting.. I use PHP to loop through all (to be) marker coordinates and calculate the values of southWest and northEast; the coords of origin are halfway between the two. If all marker coordinates are very close to each other, the zoom factor set by fitBounds is much higher (zoomed in) than the 15 used at map creation. That's why I have added that last row..

var map;

function mapInit() {
  var origin = new google.maps.LatLng(59.33344615, 18.0678188);
  var options = {
    zoom: 15,
    center: origin,
    mapTypeControlOptions: {
      mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.HYBRID]
    },
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  map = new google.maps.Map(document.getElementById("googlemap"), options);

  var southWest = new google.maps.LatLng(59.3308415, 18.0643054);
  var northEast = new google.maps.LatLng(59.3360508, 18.0713322);
  var bounds = new google.maps.LatLngBounds(southWest, northEast);
  map.fitBounds(bounds);

  google.maps.event.addListenerOnce(map, "idle", function() {
    if (map.getZoom() > 16) map.setZoom(16);
  });

So, either Google has reprogrammed the function since you posted the question or.. I need more information about your code.

Share:
26,971
abemonkey
Author by

abemonkey

New to web design. Got a pretty good handle on html and css but struggling to learn jQuery at present.

Updated on October 23, 2020

Comments

  • abemonkey
    abemonkey over 3 years

    I've created a quite complex store locator of sorts. The user enters their zip and a table returns results with corresponding markers on a map. They can page through results and the markers move further and further out and the fitbounds() function works great for zoom out to the appropriate zoom level to fit the markers. The problem is that if you page back to closer locations the fitbounds() doesn't zoom in. Even if you enter a new search it doesn't zoom in around those new markers -- it centers over them but stays at whatever zoom level it was at previously. I hope this makes sense. If anyone knows what I need to add to get it to zoom back in on closer results please help. These are the google functions that I'm call at the end of my marker pushing function:

      map.setCenter(bounds.getCenter());
      map.panToBounds(bounds);
      map.fitBounds(bounds);
    

    Thanks!

  • dbkaplun
    dbkaplun over 11 years
    This seems to work. I wonder what panToBounds is supposed to do without fitBounds.
  • gorelog
    gorelog over 11 years
    Thanks John Smith! Your suggestion was the only way I was able to get mine to zoom back in after deleting a marker. I appreciate the detail in your post.
  • Joseph Persie III
    Joseph Persie III about 8 years
    Thanks, got it working from you implementation as an angular service: gist.github.com/zmijevik/047c40f4fc0bea27fd7c
  • Darkcoder
    Darkcoder almost 5 years
    thanks only this thing worked for me tried many solutions modified little with my requirements google.maps.event.addListenerOnce(map, "idle", function() { if (map.getZoom() < parseInt(getParameterByName("zoomlevel"))) map.setZoom(parseInt(getParameterByName("zoomlevel"))); });
  • Kayote
    Kayote about 4 years
    After spending a day of search & debug, this answer was the solution. Thank you Tom.
  • Camro
    Camro almost 3 years
    For anyone reading this later on, fitBounds does Zoom with current versions, panToBounds does not and matches what is described above.