angular-google-maps center zoom multiple markers

13,456

Solution 1

Here's my code just in case anyone was wondering how to do this locally. This is a simple solution for what I needed and my indeed go back to angualr-google maps, but as of now this works fine in my application.

angular.module('myApp.controllers', [])
.controller('MapCtrl', function($scope) {
    var vm = this;
    vm.googleMap = null; 
    vm.mapMarkers = [];

    var onSuccess = function(position) {
        vm.userLocation.coords.latitude = position.coords.latitude;
        vm.userLocation.coords.longitude = position.coords.longitude;

        initializeMap();
    };

    var onError = function(error) {
        alert('code: ' + error.code + '\n' + 'message: ' + error.message);
    };

    vm.userLocation = {
        id: "home",
        title: "home",
        coords: {
            latitude: 33.636727,
            longitude: -83.920702
        },
        options: {
            animation: google.maps.Animation.BOUNCE
        }
    };

    vm.places = [
        {
            id: "78869C43-C694-40A5-97A0-5E709AA6CE51",
            title: "Place A",
            coords: {
                latitude: 33.625296,
                longitude: -83.976206
            }
        },
        {
            id: "52319278-83AA-46D4-ABA6-307EAF820E77",
            title: "Place B",
            coords: {
                latitude: 33.576522,
                longitude: -83.964981
            }
        }
    ];

    var addMarkers = function() {
        var userLocation = new google.maps.Marker({
            map: vm.googleMap,
            position: new google.maps.LatLng(vm.userLocation.coords.latitude, vm.userLocation.coords.longitude),
            //animation: vm.userLocation.options.animation,
            title: vm.userLocation.title
        });

        vm.mapMarkers.push(userLocation);

        angular.forEach(vm.places, function(location, index) {
            var marker = new google.maps.Marker({
                map: vm.googleMap,
                position: new google.maps.LatLng(location.coords.latitude, location.coords.longitude),
                title: location.title
            });
            vm.mapMarkers.push(marker);
        });

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

        for (var i = 0; i < vm.mapMarkers.length; i++) {
            bounds.extend(vm.mapMarkers[i].getPosition());
        }
        vm.googleMap.setCenter(bounds.getCenter());
        vm.googleMap.fitBounds(bounds);
        //remove one zoom level to ensure no marker is on the edge.
        vm.googleMap.setZoom(vm.googleMap.getZoom() - 1);

        // set a minimum zoom
        // if you got only 1 marker or all markers are on the same address map will be zoomed too much.
        if (vm.googleMap.getZoom() > 15) {
            vm.googleMap.setZoom(15);
        }
    };

    var initializeMap = function() {
        var mapOptions = {
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            zoom: 12,
            center: new google.maps.LatLng(vm.userLocation.coords.latitude, vm.userLocation.coords.longitude)
        };
        var div = document.getElementById("map_canvas");
        //var map = plugin.google.maps.Map.getMap(div, mapOptions);
        vm.googleMap = new google.maps.Map(div, mapOptions);
        addMarkers();

        var width = screen.width;
        var height = screen.height;
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);

})

Solution 2

Your previous answer is good but doesn't include usage of the google maps directives you mentioned in the begining of the post. There is a way to do it using those directives, here is how:

Assuming we are in the directive's scope

  1. Define scope.mapControl = {}; - this will have new access methods for map and markers

  2. When defining your markup for the directives - for map and marker - include this control attribute to be added:

    <ui-gmap-google-map center='map.center' zoom='map.zoom'    control="mapControl">
        <ui-gmap-marker ng-repeat="location in locations" coords="location.coordinates" options="location.markerOptions" idkey="location.id" control="mapControl">
            <ui-gmap-window options="location.markerWindowOptions" closeclick="closeMarkerWindow(location.id)" show="true">
                <div>{{location.description}}</div>
            </ui-gmap-window>
        </ui-gmap-marker>
    </ui-gmap-google-map>
    
  3. In your directive's event or some method:

    var map = scope.mapControl.getGMap();
    var markers = scope.mapControl.getGMarkers();
    var bounds = map.getBounds();
    for (var i = 0; i < markers.length; i++) {
        bounds.extend(markers[i].getPosition());
    }
    map.setCenter(bounds.getCenter());
    map.fitBounds(bounds);
    map.setZoom(map.getZoom() - 1);
    
Share:
13,456
GamerDev
Author by

GamerDev

Updated on June 14, 2022

Comments

  • GamerDev
    GamerDev almost 2 years

    I'm using AngularJS for Google Maps and want to dynamically center and zoom a map based on multiple markers that are dynamically loaded. This is for a Cordova app using the Ionic Framework.

    Here's my view:

    <ion-view title="" ng-controller="MapCtrl as vm">
     <ion-content class="padding">
      <google-map id="mainMap" control="vm.googleMap" draggable="true" center="vm.map.center" zoom="vm.map.zoom" mark-click="false">
          <markers idKey="mainMap" fit="vm.map.fit">
              <marker idKey="marker.id" ng-repeat="marker in vm.map.markers" coords="marker.coords" options="marker.options">
                  <marker-label content="marker.name" anchor="2 0" class="marker-labels"/>
              </marker>
          </markers>
      </google-map>
     </ion-content>
    </ion-view>
    

    Here's my controller:

    angular.module('myApp.controllers', [])
    
    .controller('MapCtrl', function($scope, $ionicPlatform) {
     var vm = this;
     vm.googleMap = {}; // this is filled when google map is initialized, but it's too late
     vm.mapMarkers = [];
    
     vm.arrMarkers = [
        {
            id: "home",
            name: "home",
            coords: {
                latitude:xxxxxxx, //valid coords
                longitude:xxxxxxx //valid coords
            },
            options: {
                animation: google.maps.Animation.BOUNCE
            }
        },
        {
            id: "placeAId",
            name: "Place A",
            coords: {
                latitude:xxxxxxx, //valid coords
                longitude:xxxxxxx //valid coords
            }
        },
        {
            id: "placeBId",
            name: "Place B",
            coords: {
                latitude:xxxxxxx, //valid coords
                longitude:xxxxxxx //valid coords
            }
        }
    ];
    vm.map = {
        center: { //how to determine where to center???
            latitude: xxxxxxx, //valid coords
            longitude: xxxxxxx //valid coords
        },
        zoom: 12, //how to determine zoom dynamically???
        fit: true,
        markers: vm.arrMarkers
    };
    
    var setMapBounds = function () {
        var bounds = new google.maps.LatLngBounds();
        createMarkers();
        var markers = vm.mapMarkers;
        for(var i=0; i<markers.length; i++) {
            bounds.extend(markers[i].getPosition());
        }
        var map = vm.googleMap.control.getGMap();
        map.setCenter(bounds.getCenter());
        map.fitBounds(bounds);
        //remove one zoom level to ensure no marker is on the edge.
        map.setZoom(map.getZoom()-1);
    
        // set a minimum zoom
        // if you got only 1 marker or all markers are on the same address map will be zoomed too much.
        if(map.getZoom()> 15){
            map.setZoom(15);
        }
    };
    
    var createMarkers = function() {
        var map = vm.googleMap.control.getGMap(); //vm.googleMap.control is undefined because this fire before map is initialized
        angular.forEach(vm.restaurants, function(restaurant, index) {
            var marker = new google.maps.Marker({
                map: map,
                position: new google.maps.LatLng(restaurant.coords.latitude, restaurant.coords.longitude),
                title: restaurant.name
            });
            vm.mapMarkers.push(marker);
        });
    };
    
    $ionicPlatform.ready(function() {
        setMapBounds();
    });
    

    })

    So, my question is how do I center and zoom the map using multiple dynamically loaded markers? Also, how do I get an instance of googleMap.control (vm.googleMap.control) before the map is loaded?