22

I have a set of GPolygon objects which are attached to objects in my domain model and are added to a map on my page. The domain objects are being shown in a list on the same page and when the user clicks on one of them I want to show the associated polygon.

I want the whole polygon to be showing and ideally I want the map to be centred on the polygon centre.

I was hoping that there would be a maps API call along the lines of...

myMap.makeSureYouCanSeeAllThisPolygon(aPolygon);

but I haven't been able to find one.

If I have to do this manually, then I can obviously figure out the centering easily, but how do I figure out the zoom?

John Conde
  • 217,595
  • 99
  • 455
  • 496
Simon
  • 78,655
  • 25
  • 88
  • 118

6 Answers6

82

Google Maps v3 API doesn't natively support a getBounds() method for the google.maps.Polygon class. This seems strange given the fact that the google.maps.Map class has a fitBounds() method, which is exactly what you're looking for.. If you use the Google Maps API with any kind of frequency then this should be in your bag of tricks ::

getBounds() method for the google.maps.Polygon class

google.maps.Polygon.prototype.getBounds = function() {
    var bounds = new google.maps.LatLngBounds();
    var paths = this.getPaths();
    var path;        
    for (var i = 0; i < paths.getLength(); i++) {
        path = paths.getAt(i);
        for (var ii = 0; ii < path.getLength(); ii++) {
            bounds.extend(path.getAt(ii));
        }
    }
    return bounds;
}

Having this method on hand makes it very simple to center and fit a polygon on the map.

Note : If you're not familiar with getAt() and getLength() that's fine, they're methods unique to the google.maps.MVCArray class. When you call the getPaths() method of a polygon it returns your array of LatLng's as a mutable MVCArray of LatLng's.. you can ready about MVCArrays here - Google Maps v3 API MVCArray class.

Moving on. Here's the framework, you'll have to implement the prototyped method above somewhere before this next bit of code.

var map = new google.maps.Map(container, opts); // I'll spare the details on this

var coords = [
    new google.maps.LatLng(25.774252, -80.190262)
    ,new google.maps.LatLng(18.466465, -66.118292)
    ,new google.maps.LatLng(32.321384, -64.75737)
    ,new google.maps.LatLng(25.774252, -80.190262)
];

var myPolygon = new google.maps.Polygon({
    paths: coords
    ,strokeColor: "#A80000"
    ,strokeOpacity: 0.8
    ,strokeWeight: 1
    ,fillColor: "#0b2a32"
    ,fillOpacity: 0.12
});

With the stage set, all you'd have to do to center and zoom on this (or any) polygon is ::

map.fitBounds(myPolygon.getBounds());
starball
  • 20,030
  • 7
  • 43
  • 238
Kevin James
  • 821
  • 6
  • 3
  • This is not working for me. console says "p" is not defined. I've noticed that google changes it variable names randomly, could this be what's happening? – Derek Dec 21 '11 at 21:01
  • @Derek `path = paths.getAt(p);` should be `path = paths.getAt(i);`. – Shef Jan 26 '12 at 13:32
  • 2
    This works really well. I'd recommend you add a condition around the getBounds() polyfill, in case Google chooses to add this natively in the future. Something like: if (!google.maps.Polygon.prototype.getBounds) – Johnny Oshika Dec 06 '13 at 06:24
  • This is a great solution, thanks! I added JohnnyO's condition as well – pmrotule Feb 13 '14 at 16:08
  • A similar [solution](http://stackoverflow.com/questions/29309856/google-maps-3-api-click-on-feature-from-geojson-and-check-if-it-contains-loc) was posted in answer to a different question. – intotecho Sep 14 '15 at 22:10
5

I wrote a function to add to Kevin James solution. it takes a polygon array and gets the bounds for all the polygons you may have on your map. you just need to push them onto an array and then you can call my function to auto zoom the map.

function getArrayBounds(polyArray){
    var bounds = new google.maps.LatLngBounds();
    var path, paths; 
    for(var polys = 0; polys < polyArray.length; polys++) {
        paths = polyArray[polys].getPaths();       
        for (var i = 0; i < paths.getLength(); i++) {
            path = paths.getAt(i);
            for (var ii = 0; ii < path.getLength(); ii++) {
                bounds.extend(path.getAt(ii));
            }
        }
    }
    return bounds;
}
Doug
  • 117
  • 1
  • 7
  • Just what I needed. However, all the `for` loops and that stuff can be done in one line: `polygonsArray.forEach(polygon => polygon.getPaths().forEach(path => path.forEach(latLng => bounds.extend(latLng))));` You would only need the first line (`let bounds = new google.maps.....`) and then the code above, and finally the `return bounds;` line :) – Javi Marzán Jan 21 '21 at 08:45
2

think he ment:

map.fitBounds(myPolygon.my_getBounds());

works a treat.

2

You can get the centre point of a polygon by using aPolygon.getBounds().getCenter(); and then using the GLatLng returned with the myMap.setCenter() method.

To get the zoom level, you can use myMap.getBoundsZoomLevel(aPolygon.getBounds()); then use this with myMap.setZoom() method.

James Goodwin
  • 7,360
  • 5
  • 29
  • 41
  • 12
    This is no longer true! Maps v3 has jettisoned the getBounds() method. – Benjamin Sep 10 '14 at 18:59
  • 2
    check this link to extend the polygon to get bounds (Google Map V3), http://tutorialspots.com/google-maps-javascript-api-v3-method-polygon-getbounds-515.html – Pradeep shyam Mar 05 '15 at 12:30
1

This solution worked for the polygons I already successfully added to the map. Adding the getBounds() method for the google.maps.Polygon class, and then using map.fitBounds(myPolygon.getBounds());

infojdem
  • 11
  • 1
0

A shorter version from the getBounds function written in ES6

google.maps.Polygon.prototype.getBounds = function () {
    let bounds = new google.maps.LatLngBounds();
    this.getPaths().forEach(p => {
        p.forEach(element => bounds.extend(element));
    });
    return bounds;
}

To center the map

map.fitBounds(poly.getBounds());
molhamaleh
  • 353
  • 3
  • 9