Google Maps JavaScript API - Automate Zoom Level?
Asked Answered
A

5

5

I'm working with multiple map markers. Currently I use map.fitBounds(bounds); in my JavaScript to resize the map. bounds contains multiple LatLng objects.

What am i doing wrong? Because it zooms out too far :-(

enter image description here

JavaScript source

var geocoder, map;
$(document).ready(function(){
    var coll_gmap = $(".gmap");
    if ( coll_gmap.length != 0 )
    {
        //initiate map
        geocoder = new google.maps.Geocoder();
        var latlng = new google.maps.LatLng(-34.397, 150.644);
        var myOptions = {
            zoom: 13,
            center: latlng,
           mapTypeControl: true,
            navigationControl: true,
            scaleControl: true,
            navigationControlOptions: {style: google.maps.NavigationControlStyle.ZOOM_PAN},
            mapTypeId: google.maps.MapTypeId.ROADMAP
        }
        var bounds = new google.maps.LatLngBounds();
        //loop all addressen + insert into map
          map = new google.maps.Map(coll_gmap[0], myOptions);
        coll_gmap.each(function(index)
        {
             if (geocoder) {
                    geocoder.geocode( { 'address': $(this).attr("address")}, function(results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            map.setCenter(results[0].geometry.location);
                            bounds.extend(results[0].geometry.location);

                            var marker = new google.maps.Marker({
                                map: map, 
                                position: results[0].geometry.location
                            });
                        } else {
                            console.log("Geocode was not successful for the following reason: " + status);
                        }//end if status
                    }); //end if geocoder.geocode
                } //end if geocoder   

        }) //end coll_gmap each
        map.fitBounds(bounds);

        }//end if coll_gmap length
       /* console.log("Script created by NicoJuicy");*/   
}); //end onload

HTML source

<div class="gmap" address="SomeAddress1" style="width:700px;height:350px"></div>
<div class="gmap" address="someAddress2"></div>
Alcatraz answered 14/7, 2010 at 11:20 Comment(0)
A
0

I have found the solution.

Instead of doing a single

bounds.extend(myLatLng)

Everytime you add a myLatLng to your bounds, do these actions

bounds = map.getBounds();
bounds.extend(results[0].geometry.location);
map.fitBounds(bounds);

Hope this helps anyone!

Alcatraz answered 16/7, 2010 at 9:3 Comment(0)
N
13

The fitBounds() method should work. However note that it always keeps some padding on the sizes of the map. Consider the following example:

<!DOCTYPE html>
<html> 
<head> 
   <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
   <title>Google Maps fitBounds Padding</title> 
   <script src="http://maps.google.com/maps/api/js?sensor=false" 
           type="text/javascript"></script> 
</head> 
<body> 
   <div id="map" style="width: 543px; height: 350px;"></div> 

   <script type="text/javascript"> 
      var map = new google.maps.Map(document.getElementById('map'), { 
        mapTypeId: google.maps.MapTypeId.ROADMAP 
      });

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

      var points = [
        new google.maps.LatLng(51.22, 4.40),
        new google.maps.LatLng(50.94, 3.13)
      ];

      // Extend bounds with each point
      for (var i = 0; i < points.length; i++) {
        bounds.extend(points[i]);
        new google.maps.Marker({position: points[i], map: map});
      }

      // Apply fitBounds
      map.fitBounds(bounds);  

      // Draw the bounds rectangle on the map
      var ne = bounds.getNorthEast();
      var sw = bounds.getSouthWest();

      var boundingBox = new google.maps.Polyline({
        path: [
          ne, new google.maps.LatLng(ne.lat(), sw.lng()),
          sw, new google.maps.LatLng(sw.lat(), ne.lng()), ne
        ],
        strokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2
      });

      boundingBox.setMap(map);
   </script> 
</body> 
</html>

Screenshot from the above example:

Google Maps fitBounds Padding

The red bounding box represents the LatLngBounds object when extended with both markers. Note that the map canvas is 543px wide, and also note the padding margin to the left and right of the bounding box.

Now if we reduce the width of the map canvas by just 1px, using 542px, the fitBounds() method will pop to a lower zoom level:

Google Maps fitBounds Padding

Nava answered 14/7, 2010 at 23:11 Comment(2)
Nice reaction. Still, i have to wonder, if you notice my screenshot, my markers aren't in the middle, more on the left half. So something else has to be wrong, also, the zoom doesn't get "closer" when i adjust the width...Alcatraz
@NicoJuicy: Is it possible to update your question with a full example that replicates your problem? I tried to place the markers at the same location as yours, and fitBounds() appears to be working much better in my screenshots.Nava
D
6

I got here using a "Related" link to the right, and I think that the answer to your problem is the same as to the previous question. :p

See, the thing is that every time you use a function that pans/zooms the map, the script ignores new, similar, input until it's ready for it again. Therefore, you have to detect this and only call fitBounds() when it's accepted. Try replacing your

map.fitBounds(bounds);

with

var listener = google.maps.event.addListener(map, "idle", function() { 
               map.fitBounds(bounds);
               google.maps.event.removeListener(listener); });

Good luck.

Durazzo answered 3/11, 2010 at 15:37 Comment(0)
S
1

Just use the setZoom function.

var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': zipcode }, function(results, status)
{
    if (status == google.maps.GeocoderStatus.OK)
    {
        map.setCenter(results[0].geometry.location);
        map.setZoom(12);
    }
    else
    {
        alert(zipcode + " not found" + "\nstatus : " + status);
    }
});
Sledgehammer answered 3/12, 2012 at 18:7 Comment(0)
A
0

I have found the solution.

Instead of doing a single

bounds.extend(myLatLng)

Everytime you add a myLatLng to your bounds, do these actions

bounds = map.getBounds();
bounds.extend(results[0].geometry.location);
map.fitBounds(bounds);

Hope this helps anyone!

Alcatraz answered 16/7, 2010 at 9:3 Comment(0)
B
0
//Custom zoom if you have just type of geocode response    
function get_node(node_name){
return document.getElementById(node_name);
}

var map_options = {};
var options = {
    'zoom'      : LB_listing.zoomopt,
    'minZoom'   : 3,
    'center'    : latlng,
    'mapTypeId' : google.maps.MapTypeId.ROADMAP
};
map_options.map = new google.maps.Map(get_node('googleMap'), options);


geocoder = new google.maps.Geocoder();
var address = $("#search_location").val();
geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
        switch(results[0].types[0]){
            case 'street_address':
                map_options.zoomopt = 6;
                break;
            case 'route':
                map_options.zoomopt = 14;
                break;
            case 'bus_station':
                map_options.zoomopt = 14;
                break;
            case 'intersection':
                map_options.zoomopt = 6;
                break;
            case 'political':
                map_options.zoomopt = 14;
                break;
            case 'country':
                map_options.zoomopt = 5;
                break;
            case 'administrative_area_level_1':
                map_options.zoomopt = 6;
                break;
            case 'administrative_area_level_2':
                map_options.zoomopt = 6;
                break;
            case 'administrative_area_level_3':
                map_options.zoomopt = 6;
                break;
            case 'administrative_area_level_4':
                map_options.zoomopt = 6;
                break;
            case 'administrative_area_level_5':
                map_options.zoomopt = 6;
                break;
            case 'colloquial_area':
                map_options.zoomopt = 6;
                break;
            case 'locality':
                map_options.zoomopt = 11;
                break;
            case 'ward':
                map_options.zoomopt = 6;
                break;
            case 'sublocality':
                map_options.zoomopt = 6;
                break;
            case 'neighborhood':
                map_options.zoomopt = 14;
                break;
            case 'premise':
                map_options.zoomopt = 6;
                break;
            case 'subpremise':
                map_options.zoomopt = 6;
                break;
            case 'postal_code':
                map_options.zoomopt = 6;
                break;
            case 'natural_feature':
                map_options.zoomopt = 6;
                break;
            case 'airport':
                map_options.zoomopt = 6;
                break;
            case 'park':
                map_options.zoomopt = 6;
                break;
            case 'point_of_interest':
                map_options.zoomopt = 6;
                break;
            default:
                map_options.zoomopt = 6;
                break;
        }
        map_options.newLocation(results[0].geometry.location.lat(),results[0].geometry.location.lng());
    }else {
        $('#message_error').show().delay(3000).fadeOut(1000);
        $('#message_error_msg').html("Geocode was not successful for the following reason: " + status);
    }
});

map_options.newLocation = function(newLat,newLng) {
map_options.map.setCenter({
    lat : newLat,
    lng : newLng
});
map_options.map.setZoom(map_options.zoomopt);

}

Bostic answered 21/10, 2016 at 9:15 Comment(1)
Welcome to SO. Your input is always welcome, but usually some annotation is nice, tooTombouctou

© 2022 - 2024 — McMap. All rights reserved.