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 result
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
}
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.
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);
fitBounds: function(bounds, mapId)
{
//bounds: bounds, id: map id
if (bounds==null) return false;
maps[mapId].fitBounds(bounds);
},
This should help, i use this method and works fine, on map v2 a little bit different way.
Make sure there are no CSS animations on the width or height of your map. The animations interfere with the zoom behaviour of fitBound()
I spent most of the day on this problem yesterday, and I encountered this StackOverflow post at least a dozen times. But I eventually had to find the problem the hard way on my own.
Deleting the transition: all 0.5s ease;
line below fixed it for me.
.google-map {
width: 100%;
height: 0px;
transition: all 0.5s ease;
}
.google-map.loaded {
height: 400px;
}
I also had an issue with the map zooming way out when calling fitBounds a second time on the same map with new markers. This is the frankensolution that works for me:
// This is a stationary point tho dynamic will work too
var myLat = someLat,
myLng = someLong;
var map = false,
markersArray = [];
function makeOrderMap(lat, lng) { // pass in dynamic point when updating map
var mapOptions = {
center: new google.maps.LatLng(myLat, myLng),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
deleteOverlays(); // remove any existing markers..
if(!map) {
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
// Find the mid-point to center the map
midLat = (parseFloat(lat) + parseFloat(myLat)) / 2;
midLng = (parseFloat(lng) + parseFloat(myLng)) / 2;
map.setCenter(new google.maps.LatLng(midLat, midLng));
var newSpot = new google.maps.LatLng(lat, lng);
placeMarker(mapOptions.center);
placeMarker(newSpot);
// determine the distance between points for deciding the zoom level
var dist = distHaversine(mapOptions.center, newSpot);
var zoom = 10;
if(dist < 1.25) {
zoom = 15;
} else if(dist < 2.5) {
zoom = 14;
} else if(dist < 5) {
zoom = 13;
} else if(dist < 10) {
zoom = 12;
} else if(dist < 20) {
zoom = 11;
}
map.setZoom(zoom);
}
rad = function(x) {return x*Math.PI/180;}
distHaversine = function(p1, p2) {
var R = 6371; // earth's mean radius in km
var dLat = rad(p2.lat() - p1.lat());
var dLong = rad(p2.lng() - p1.lng());
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d.toFixed(3);
}
function deleteOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray = [];
markersArray.length = 0;
}
}
function placeMarker(location, alt_icon) {
var marker = new google.maps.Marker({
position: location,
map: map
});
// add marker in markers array
markersArray.push(marker);
}