3

I am using ng-map and trying to show multiple markers on the google map. When the page loads I would like to see all the markers on the map scattered across countries.

The map is showing only a zoomed in portion of one marker. May be this is because I am assigning the map center to the last item in the array. When I scroll/zoom in and out of the map, I can then see all the markers.

I am not sure what the map center should be when there are multiple markers and how do I get a map view that will show all the markers when the map loads

Here is the code:

controller:

$scope.cityMetaData = [];
$scope.getCityInfo = function(){
    for(var i=0; i<$scope.cityIds.length; i++){
        var id = $scope.cityIds[i];
        GetCity.query({cityid: id}, function(data) { 
            if (data.status == "success") {
                var cityData = data;
                $scope.cityMetaData.push(cityData);
                $scope.addressMarker(cityData);
            }
        });
    }
}

$scope.addressMarker = function(cityItem) {
    var address = cityItem.cityName;
    geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'address' : address
    }, function(results, status) {
        if ( status == google.maps.GeocoderStatus.OK ) {
            $scope.lat = results[0].geometry.location.lat();
            $scope.lng = results[0].geometry.location.lng();
            $scope.markerData.push({
                "latitude" : results[0].geometry.location.lat(),
                "longitude" : results[0].geometry.location.lng(),
                "title" : results[0].formatted_address
            });
        } else {
            $log.info('Geocode was not successful for the following reason:' + status);
        }
    });
}
$scope.getCityInfo();

html:

<map center="[{{lat}},{{lng}}]" zoom="8" style="display:block; width:auto; height:auto;"> 
    <marker ng-repeat="pin in markerData" position="{{pin.latitude}},{{pin.longitude}}" title="{{pin.title}}"></marker>
</map>

sample $scope.markerData array :

[{"latitude":38.232417,"longitude":-122.6366524,"title":"Petaluma, CA, USA"},
{"latitude":34.1477849,"longitude":-118.14451550000001,"title":"Pasadena, CA, USA"},
{"latitude":40.7556818,"longitude":-73.8830701,"title":"Jackson Heights, Queens, NY, USA"},
{"latitude":32.7766642,"longitude":-96.79698789999998,"title":"Dallas, TX, USA"},
{"latitude":37.7974273,"longitude":-121.21605260000001,"title":"Manteca, CA, USA"},
{"latitude":37.48521520000001,"longitude":-122.23635480000002,"title":"Redwood City, CA, USA"}]
Mustang
  • 604
  • 2
  • 13
  • 32

2 Answers2

1

That's right, it occurs since the center and zoom properties are specified explicitly. In order to center and zoom automatically with respect to the markers fitBounds() function is intended.

In angularjs-google-maps component you could specify zoom-to-include-markers attribute for that purpose:

<map zoom-to-include-markers="true" style="display:block; width:auto; height:auto;">
    <marker ng-repeat="pin in markerData" position="{{pin.latitude}},{{pin.longitude}}" title="{{pin.title}}"></marker>
</map>

Modified example

angular.module('mapApp', ['ngMap'])
    .controller('mapController', function (NgMap, $scope, $q, $log) {

        $scope.lat = 38.232417;
        $scope.lng = -122.6366524;

        $scope.markerData = [];
        $scope.cityMetaData = [];
        $scope.getCityInfo = function () {
            /*for (var i = 0; i < $scope.cityIds.length; i++) {
                var id = $scope.cityIds[i];
                GetCity.query({ cityid: id }, function (data) {
                    if (data.status == "success") {
                        var cityData = data;
                        $scope.cityMetaData.push(cityData);
                        $scope.addressMarker(cityData);
                    }
                });
            }*/

            var data = [
                { cityName: 'Petaluma, CA, USA' },
                { cityName: 'Pasadena, CA, USA' },
                { cityName: 'Jackson Heights, Queens, NY, USA' },
                { cityName: 'Dallas, TX, USA' },
                { cityName: 'Manteca, CA, USA' },
                { cityName: 'Redwood City, CA, USA' },
            ];
            data.forEach(function (item) {
                var cityData = item;
                $scope.cityMetaData.push(cityData);
                $scope.addressMarker(cityData);
            });


        }

        $scope.addressMarker = function (cityItem) {
            var deferred = $q.defer();
            var address = cityItem.cityName;
            var geocoder = new google.maps.Geocoder();
            geocoder.geocode({
                'address': address
            }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    $scope.$apply(function () {
                        $scope.markerData.push({
                            "latitude": results[0].geometry.location.lat(),
                            "longitude": results[0].geometry.location.lng(),
                            "title": results[0].formatted_address
                        });
                    });
                } else {
                    $log.info('Geocode was not successful for the following reason:' + status);
                }
            });
        }
        $scope.getCityInfo();
    });
<script src="https://maps.google.com/maps/api/js"></script>
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<div ng-app="mapApp" ng-controller="mapController">
 
    <map zoom-to-include-markers="true" style="display:block; width:auto; height:auto;">
        <marker ng-repeat="pin in markerData" position="{{pin.latitude}},{{pin.longitude}}" title="{{pin.title}}"></marker>
    </map>
</div>

Example 2

angular.module('mapApp', ['ngMap'])
    .controller('mapController', function (NgMap, $scope, $q, $log) {

        NgMap.getMap().then(function(map) {
            $scope.map = map;
        });   
        
        $scope.currentPin = {title: ""};
        $scope.markerData = [];
        $scope.cityMetaData = [];
        $scope.getCityInfo = function () {
            
            var data = [
                { cityName: 'Petaluma, CA, USA' },
                { cityName: 'Pasadena, CA, USA' },
                { cityName: 'Jackson Heights, Queens, NY, USA' },
                { cityName: 'Dallas, TX, USA' },
                { cityName: 'Manteca, CA, USA' },
                { cityName: 'Redwood City, CA, USA' },
            ];
            data.forEach(function (item) {
                var cityData = item;
                $scope.cityMetaData.push(cityData);
                $scope.addressMarker(cityData);
            });
        }


        $scope.showDetail = function (e, pin) {
          $scope.currentPin = pin;
          $scope.map.showInfoWindow('iw', this);
        };

        $scope.hideDetail = function () {
           $scope.map.hideInfoWindow('iw');
        };

        $scope.addressMarker = function (cityItem) {
            var deferred = $q.defer();
            var address = cityItem.cityName;
            var geocoder = new google.maps.Geocoder();
            geocoder.geocode({
                'address': address
            }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    $scope.$apply(function () {
                        $scope.markerData.push({
                            "latitude": results[0].geometry.location.lat(),
                            "longitude": results[0].geometry.location.lng(),
                            "title": results[0].formatted_address
                        });
                    });
                } else {
                    $log.info('Geocode was not successful for the following reason:' + status);
                }
            });
        }
        $scope.getCityInfo();
    });
<!--link href="style.css" rel="stylesheet"-->
<script src="https://maps.google.com/maps/api/js"></script>
<script src="https://code.angularjs.org/1.2.23/angular.js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<script src="map.js"></script>

<div ng-app="mapApp" ng-controller="mapController">
    <map zoom-to-include-markers="true" style="display:block; width:auto; height:auto;">
        <marker ng-repeat="pin in markerData" position="{{pin.latitude}},{{pin.longitude}}" title="{{pin.title}}" on-click="showDetail(pin)"></marker>
        <info-window id="iw">
           <div ng-non-bindable="">
                <!--h1>{{currentPin.title}}</h1--> 
           </div>
        </info-window>
    </map>
</div>
Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • Per your suggestion, I tried the "zoom-to-include-marker" attribute. When the map loads the 1st time I can see all the markers. When I close the popup and open it back again, the map loads into an ocean. So, basically the map loads perfectly only one time. Any ideas why it is behaving this way? – Mustang Feb 02 '16 at 16:34
  • Unfortunately i can not reproduce such kind of behavior but the answer has been updated to demonstrate how to display info window (**example 2**) – Vadim Gremyachev Feb 02 '16 at 22:58
0

If there is a way to change the "maps" plugin for that, I recommend you to take a look at

http://angular-ui.github.io/angular-google-maps/

here you get a quite similar API as on ngMaps, but gaining more fine grained options e.g. ng-templates inside info windows over markers etc....

In their implementation, they automatically zoom to markers, when you generate some. But you are free to hook in via events to make your own decision

David Steiman
  • 3,055
  • 2
  • 16
  • 22
  • Thanks. I would like to find a solution to my problem :-) If there is no way to do it then I might think of using alternatives. – Mustang Jan 29 '16 at 22:07