Google Maps v3: Enforcing min. zoom level when using fitBounds
Solution 1
At this discussion on Google Groups I discovered that basically when you do a fitBounds, the zoom happens asynchronously so you need to capture the zoom and bounds change event. The code in the final post worked for me with a small modification... as it stands it stops you zooming greater than 15 completely, so used the idea from the fourth post to have a flag set to only do it the first time.
// Do other stuff to set up map
var map = new google.maps.Map(mapElement, myOptions);
// This is needed to set the zoom after fitbounds,
google.maps.event.addListener(map, 'zoom_changed', function() {
zoomChangeBoundsListener =
google.maps.event.addListener(map, 'bounds_changed', function(event) {
if (this.getZoom() > 15 && this.initialZoom == true) {
// Change max/min zoom here
this.setZoom(15);
this.initialZoom = false;
}
google.maps.event.removeListener(zoomChangeBoundsListener);
});
});
map.initialZoom = true;
map.fitBounds(bounds);
Hope that helps,
Anthony.
Solution 2
Without trying it, I'd say you should be able to do it just by having fitBounds()
before you get the zoom level, i.e.
map.fitBounds(bounds);
var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);
If you did try that and it didn't work, you can setup your map with minZoom
in the MapOptions
(api-reference) like this:
var map = new google.maps.Map(document.getElementById("map"), { minZoom: 6 });
This would keep the map from zooming any further out when using fitBounds()
.
Solution 3
You can also set the maxZoom option just before calling fitBounds() and reset the value afterwards:
if(!bounds.isEmpty()) {
var originalMaxZoom = map.maxZoom;
map.setOptions({maxZoom: 18});
map.fitBounds(bounds);
map.setOptions({maxZoom: originalMaxZoom});
}
Solution 4
Anthony's solution is very nice. I only needed to fix the zoom for the inital page load (ensuring that you weren't too far zoomed in to start with) and this did the trick for me:
var zoomChangeBoundsListener =
google.maps.event.addListener(map, 'bounds_changed', function(event) {
google.maps.event.removeListener(zoomChangeBoundsListener);
map.setZoom( Math.min( 15, map.getZoom() ) );
});
map.fitBounds( zoomBounds );
Solution 5
When you call map.fitBounds() on one item - the map may zoom in too closely. To fix this, simply add 'maxZoom' to mapOptions...
var mapOptions = {
maxZoom: 15
};
Related videos on Youtube
chris
Updated on January 06, 2021Comments
-
chris over 3 years
I'm drawing a series of markers on a map (using v3 of the maps api).
In v2, I had the following code:
bounds = new GLatLngBounds(); ... loop thru and put markers on map ... bounds.extend(point); ... end looping map.setCenter(bounds.getCenter()); var level = map.getBoundsZoomLevel(bounds); if ( level == 1 ) level = 5; map.setZoom(level > 6 ? 6 : level);
And that work fine to ensure that there was always an appropriate level of detail displayed on the map.
I'm trying to duplicate this functionality in v3, but the setZoom and fitBounds don't seem to be cooperating:
... loop thru and put markers on the map var ll = new google.maps.LatLng(p.lat,p.lng); bounds.extend(ll); ... end loop var zoom = map.getZoom(); map.setZoom(zoom > 6 ? 6 : zoom); map.fitBounds(bounds);
I've tried different permutation (moving the fitBounds before the setZoom, for example) but nothing I do with setZoom seems to affect the map. Am I missing something? Is there a way to do this?
-
chris almost 14 yearsThank you! I've been fighting with that for a couple of hours! It does seem like a bug, though.
-
Metro Smurf over 12 yearsThis is a good method. Another method is to check the current bounds and extend the bounds, i.e., stackoverflow.com/questions/3334729/… . Though the linked answer here is only expanding the bounds by a fraction, you can use the same method to expand the bounds by a larger number; I've found that adding 7 to all corners does a good job.
-
Andrew over 12 yearsThis is a cool solution. I noticed, however, that it works fine for me in chrome, ie, and firefox without using map.initialZoom.
-
Jan Aagaard over 12 yearsI don't think map.initialZoom is needed, since the event removes itself once it fires. A great solution, nevertheless.
-
Andrew over 12 yearsI'd like to correct my previous comment. I think that setting the initialZoom property might be needed. I had some trouble zooming in real close on IE 9 after leaving out that part of the code... Cool solution!
-
pstadler over 11 yearsUse
google.maps.event.addListenerOnce()
, so you don't have to manually remove the listener afterwards. -
Falantar014 about 11 yearsnice simple and elegant solution!
-
Izazael over 10 yearsSetting the minZoom and maxZoom values restricts the user from zooming beyond those values, so it doesn't help if all you want to do is set the initial zoom to something reasonable (which is what I think the OP was talking about)
-
Flygenring over 10 yearsSo basically pretty much exactly as I wrote in my answer?
-
Selwyn over 9 yearsthe variable zoomChangeBoundsListener throws an execption as its undefined and hence the map is stuck. Is this the correct code snippet
-
Derek over 9 yearsInstead of removing the listener you can use
addListenerOnce
, but I am using this solution. -
sba almost 9 yearsBecause I've been looking at this the third time, here's the golfed version. Thanks @pstadler.
google.maps.event.addListenerOnce(map, 'bounds_changed', function() { this.setZoom(Math.min(15, this.getZoom())); });
-
Flygenring over 7 yearsThis seems to be the only answer that should actually use
addListener
instead of repeating (and relying on remembering) toaddListenerOnce
before every singlemap.fitBounds()
-
Milk Man almost 7 yearsWhen using addLIstenerOnce you can simply listen
zoom_changed
. I'm usingzoom_changed
just beforemap.fitBounds(bounds);
and seems to work great on Chrome. -
Rich Court over 5 years@Izazael makes a good point, that isn't covered in the answer. This is great at stopping
fitBounds()
from zooming too far, but it also restricts the user's interaction with the map's zoom buttons. The accepted answer is the better option if you prefer that the user have full control. -
Flygenring over 5 yearsI'm not really sure how it's not covered by my answer, as I mention the second technique stating: "This would keep the map from zooming any further"
-
RubbelDeCatc over 4 yearsMight not work because wit new versions. fitBounds() works asynchronous!
-
Greg over 4 yearsI like this option because it does not cause the
zoom_changed
event to fire twice like many of the other options -
Alexey Domanski about 4 yearsAwesome solution when max object has maxZoom option defined.