16

I have a dynamically generated list of markers within my Google Map. I want the map's center to be the center of all the markers and zoomed out just enough so that all markers are in view.

In terms of calculating the map center, perhaps this could be possible by iterating through all the latitudes and longitudes and finding the central point. However, I cannot figure out the best way to calculate what the zoom should be.

Is this possible to achieve?

My map is being used in the template like this:

<ui-gmap-google-map events="map.events" center="map.center" zoom="map.zoom" draggable="true" options="options">
    <ui-gmap-marker ng-repeat="home in filteredHomes = (resCtrl.filteredHomes | orderBy : $storage.params.orderby : $storage.params.reverseOrder)" coords="{latitude: home.location.latitude, longitude: home.location.longitude}" idkey="home.homeId">
    </ui-gmap-marker>
</ui-gmap-google-map>

UPDATE

Attempted Angular implementation from advice from @Tiborg:

uiGmapGoogleMapApi.then(function(maps) {
    $scope.map = {
        center: $scope.$storage.params.views.map.location,
        zoom: $scope.$storage.params.views.map.zoom,
        events: {
            click: function() {
                var bounds = new google.maps.LatLngBounds();
                for (var i in $scope.filteredHomes) {
                    bounds.extend($scope.filteredHomes[i].location);
                }
                $scope.map.fitBounds(bounds);
            }
        }
    };
});

This produces the console error: TypeError: undefined is not a function (evaluating 'a.lat()')

Fisu
  • 3,294
  • 9
  • 39
  • 61
  • It's hard to tell what's the problem without knowing the flow of your program and what each member / variable contains. Search for me in the chat rooms and start a conversation, so we're not discussing here on the comment section. – Tiborg Dec 17 '14 at 09:09
  • Hey Fisu, Does the above code work automatically. Why is setting the bounds attached to a click event vs automatically happening when map gets displayed on the page? Curious if you have a jdfiddle you can share that is working. – armyofda12mnkeys Apr 22 '15 at 04:45
  • @armyofda12mnkeys yeah you're right, I ended up using the option `fit: true` not attached to a click event. – Fisu Apr 22 '15 at 07:23

5 Answers5

19

Use the LatLngBounds class in Google Maps API, like this:

var bounds = new google.maps.LatLngBounds();
for (var i in markers) // your marker list here
    bounds.extend(markers[i].position) // your marker position, must be a LatLng instance

map.fitBounds(bounds); // map should be your map class

It will nicely zoom and center the map to fit all your markers.

Of course, this is the pure javascript, not the angular version, so if you have problems implementing it in angular (or you don't have access to the map instance from where you get the markers), let me know.

Tiborg
  • 2,304
  • 2
  • 26
  • 33
  • Thanks. I am having problems implementing it in Angular. I think it might be the `new google.maps...` that's causing the problems. In my Angular app, the map functionality happens here: `uiGmapGoogleMapApi.then(function(maps) {...` therefore, do I replace `new google.maps` with `new maps`? – Fisu Dec 16 '14 at 05:41
  • Have updated my question using your suggestion. Can you see what else I could be doing wrong? – Fisu Dec 16 '14 at 07:22
  • 1
    Was using the wrong maps reference. Now working, thanks – Fisu Dec 17 '14 at 09:58
18

angular-google-maps has taken care of this feature. All you need to do is add fit="true" attribute in your markers directive (ui-gmap-markers). Example : <ui-gmap-markers models="map.markers" fit="true" icon="'icon'"> Please refer the document http://angular-ui.github.io/angular-google-maps/#!/api

Hasteq
  • 926
  • 13
  • 21
  • Not sure it helps entirely. I thought I tested this few days ago and I still had to set a center on the ui-gmap-google-map directive (i set it so it was the 'home' location), and then from that center the fit attribute on ui-gmap-markers then seems to zooms out and covers nearby locations (covering quite a large distance than I'd expect), versus just auto-centering to fit all the points (like i dont necessarily want my home location to be exactly in the middle). – armyofda12mnkeys Apr 22 '15 at 04:40
  • I got your point. It may not cover all the scenarios but will help most of the common needs. For specific needs such as your you may play with the bounds' northeast and southwest properties. I don't know if that would be of any help with your scenario – Hasteq Apr 24 '15 at 21:54
  • It doesn't automatically set the center. Only zooms. – Aysennoussi May 06 '16 at 06:43
  • It's a mix, use the google.maps.LatLngBounds to calculate the center of the map, and the fit="'true'" it works perfect for me, that way you don't need a map instance, just use center: { latitude: bounds.getCenter().lat(), longitude: bounds.getCenter().lng() } – Camilo Casadiego Dec 17 '16 at 00:37
6

The answer has been posted for another problem: https://stackoverflow.com/a/23690559/5095063 After that you have just to add this line:

$scope.map.control.getGMap().fitBounds(bounds);
Community
  • 1
  • 1
Aminovski
  • 145
  • 1
  • 5
4

Thanks to all the replies, I got this code which is working perfectly for me:

var bounds = new google.maps.LatLngBounds();
for (var i = 0, length = $scope.map.markers.length; i < length; i++) {
  var marker = $scope.map.markers[i];
  bounds.extend(new google.maps.LatLng(marker.latitude, marker.longitude));
}
$scope.map.control.getGMap().fitBounds(bounds);

I hope it will help to someone.

Jesús Sobrino
  • 387
  • 2
  • 5
  • 1
    Hi, can we have a working plunkr.co example where this solution working fine? I've tried the solution but it's not working... – Ravimallya Jul 31 '16 at 11:50
0

Also use timeout to make sure it is digested properly

 uiGmapIsReady.promise()
          .then(function (map_instances) {
            var bounds = new google.maps.LatLngBounds();
            for (var i in $scope.map.markers) {
              var marker = $scope.map.markers[i];
  bounds.extend(new google.maps.LatLng(marker.latitude, marker.longitude));
            }

            $timeout(function() {
              map_instances[0].map.fitBounds(bounds);
            }, 100);
          });