Maps API V3 () API Scales But Never

I created a pretty sophisticated storage locator. The user enters his zip code, and the table returns the results with the corresponding markers on the map. They can view pages, and markers move farther and farther, and the fitbounds() function works great to scale down to the appropriate zoom level so that it matches the markers. The problem is that if you go to closer locations, fitbounds() does not increase. Even if you introduce a new search, it does not approach the new markers - it is centered above them, but remains at any zoom level it was before. I hope this makes sense. If someone knows what I need to add in order to get it in order to return to closer results, please help. These are the google functions that I call at the end of the marker push function:

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

Thanks!

+6
jquery google-maps google-maps-api-3
source share
9 answers

The problem is this: we install

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

so that we can later place our markers in a limited area on the map. GMaps will always zoom out asynchronously for fitBounds () respectively, but will not zoom in to achieve the same (as @broady previously noted). This is not ideal for many applications, because after you have left and displayed a number of markers on the map, due to which the map was reduced (possibly <10), it will not be manually scaled without a user.

GMaps will continue to use boundaries (lack of better words) that have most changed marker collection status (sorry). Setting "null" before each call of new markers gives you a new map to work with.

To scale automatically, just set LatLngBounds (); for a โ€œnullโ€ value (see the 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 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 } 
+9
source share

Nothing needed here. Set the borders first, then the pan. This will give you the correct scale and will contain all the borders.

 map.fitBounds(bounds); map.panToBounds(bounds); 
+7
source share

That's right, fitBounds provides only visible borders. He does not approach the appropriate level.

You can call setZoom(20) and then fitBounds.

+4
source share

Hmm, interesting. I use PHP to scroll through all (to) marker coordinates and calculate the values โ€‹โ€‹of southWest and northEast; origin coords are halfway between them. If all marker coordinates are very close to each other, the scale factor specified by fitBounds is much higher (increased) than the 15 used to create the map. That is why I added this last line.

 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 reprogrammed the function since you posted a question or ... I need more information about your code.

+3
source share

It turns out that when you call map.getBounds() , it returns a viewport with a small margin at the edges. Since this new border is larger than the current borders, the map will always shrink. I was able to solve it, avoiding the use of the current map borders as a whole and supporting a separate LatLngBounds variable. Each time I added a point that I called:

 markersBounds.extend(newMarkersLatLng); map.fitBounds(markersBounds); map.panToBounds(markersBounds); 

To remove points (I always added them), you could create a new LatLngBounds object with the first point, and then expand each remaining point to get new borders:

 var markersBounds = new google.maps.LatLngBounds(markers[0].getPosition(), markers[0].getPosition()); for(var i=1; i<markers.length; i++){ markersBounds.extend(markers[i].getPosition()); } map.fitBounds(markersBounds); map.panToBounds(markersBounds); 
+1
source share

I also had a problem displaying the map when you called 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 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); } 
+1
source share
 map.setZoom(10); 

I believe that the acceptable range is 1-20. Only integers, decimals broke the map in my experience.

0
source share
 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 work fine, on map v2 a little differently.

0
source share

Today I came across this common problem, I thought that I would share a solution. I understand that this is slightly different from your storage vault problem, but it applies in many ways. In my case, I have a collection of markers on the map, and I add it and want all the markers to be in sight now. This code checks each existing marker to see if it will be in the view and along the way creates a new bounding box that will contain them all, if necessary. In the end, if it was found that it was not visible, the view is reset, so that is all of them.

(the Dojo array module is used, just a convenient wrapper around the main iteration of the array)

 var origBounds = map.getBounds(), newBounds = new google.maps.LatLngBounds(null), anyFailed = false; array.forEach(markers, function (m) { newBounds.extend(m.position); if (!origBounds.contains(m.position)) { anyFailed = true; } }); if (anyFailed) { map.setCenter(newBounds.getCenter()); map.fitBounds(newBounds); } 

You can easily change this to make sure that the new marker is in view without looping and just does a contains () check on the new marker.

0
source share

All Articles