Sunday, 31 May 2015

Using Google Map Geolocation API with AngularJS..

When I first start working on google map  for Angular JS, excitement went through my nerves and started realizing how angular js made everything so simple. This is probably the second one on google map and I came to learn about this from one of JSFiddle. So I have tried to make a little modification and finally came out with this.
This module contains two utilities. 1. Finding your current location 2. Searching a particular location. Markers are also added with hard-coded array elements containing name of cities and it's coordinates. Filters are also applied to convert decimal coordinated to degree minutes and seconds. I hope you find this angularjs tutorial helpful.

<!-- HTML module -->

<!DOCTYPE html>
<html>
<body ng-app="app" ng-controller="appCtrl">
<script
    src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<script
    src="http://maps.googleapis.com/maps/api/js?sensor=false&language=en"></script>
  <script type="text/javascript" src="geoLoc.js"></script>
<h3>Google Maps</h3>

    <!-- search/go to current location -->
    <div class="text-right">
        <div class="input-append text-right">
            <input type="text" ng-model="search"/>
            <button class="btn" type="button" ng-click="geoCode()" ng-disabled="search.length == 0" title="search" >
              &nbsp;<i class="icon-search"></i>Where is this place?
            </button>
            <button class="btn" type="button" ng-click="gotoCurrentLocation()" title="current location">
              &nbsp;<i class="icon-home"></i>Where am I now?
            </button>
        </div>
    </div>

    <!-- map -->
    <app-map style="height:400px;margin:12px;box-shadow:0 3px 25px black;"
        center="loc"
        markers="cities"  >
    </app-map>

    <!-- current location -->
    <div class="text-info text-right">
        {{loc.lat | lat:0}}, {{loc.lon | lon:0}}
    </div>

    <!-- list of cities -->
    <div class="container-fluid">
        <div class="span3 btn"
            ng-repeat="a in cities"
            ng-click="gotoLocation(a.lat, a.lon)">
            <b>{{a.place}}</b>: {{a.desc}}
        </div>
    </div>
</body>
</html
/* JS module */

var app = angular.module("app", []);

app.controller("appCtrl", function ($scope) {

    // current location
    $scope.loc = { lat: 23, lon: 79 };
    $scope.gotoCurrentLocation = function () {
        if ("geolocation" in navigator) {
            navigator.geolocation.getCurrentPosition(function (position) {
                var c = position.coords;
                $scope.gotoLocation(c.latitude, c.longitude);
            });
            return true;
        }
        return false;
    };
    $scope.gotoLocation = function (lat, lon) {
        if ($scope.lat != lat || $scope.lon != lon) {
            $scope.loc = { lat: lat, lon: lon };
            if (!$scope.$$phase) $scope.$apply("loc");
        }
    };

    // geo-coding
    $scope.search = "";
    $scope.geoCode = function () {
        if ($scope.search && $scope.search.length > 0) {
            if (!this.geocoder) this.geocoder = new google.maps.Geocoder();
                  this.geocoder.geocode({ 'address': $scope.search }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var loc = results[0].geometry.location;
                    $scope.search = results[0].formatted_address;
                    $scope.gotoLocation(loc.lat(), loc.lng());
                } else {
                    alert("Sorry, this search produced no results.");
                }
            });
        }
    };

 $scope.cities = [
              {
                  place : 'India',
                  desc : 'A country of culture and tradition!',
                  lat : 23.200000,
                  lon : 79.225487
              },
              {
                  place : 'New Delhi',
                  desc : 'Capital of India...',
                  lat : 28.500000,
                  lon : 77.250000
              },
              {
                  place : 'Kolkata',
                  desc : 'City of Joy...',
                  lat : 22.500000,
                  lon : 88.400000
              },
              {
                  place : 'Mumbai',
                  desc : 'Commercial city!',
                  lat : 19.000000,
                  lon : 72.90000
              },
              {
                  place : 'Bangalore',
                  desc : 'Silicon Valley of India...',
                  lat : 12.9667,
                  lon : 77.5667
              }
          ];   
});

// formats a number as a latitude (e.g. 20.46... => "20°27'44"N")
app.filter('lat', function () {
    return function (input, decimals) {
        if (!decimals) decimals = 0;
        input = input * 1;
        var ns = input > 0 ? "N" : "S";
        input = Math.abs(input);
        var deg = Math.floor(input);
        var min = Math.floor((input - deg) * 60);
        var sec = ((input - deg - min / 60) * 3600).toFixed(decimals);
        return deg + "°" + min + "'" + sec + '"' + ns;
    }
});

// formats a number as a longitude (e.g. -80.02... => "80°1'24"W")
app.filter('lon', function () {
    return function (input, decimals) {
        if (!decimals) decimals = 0;
        input = input * 1;
        var ew = input > 0 ? "E" : "W";
        input = Math.abs(input);
        var deg = Math.floor(input);
        var min = Math.floor((input - deg) * 60);
        var sec = ((input - deg - min / 60) * 3600).toFixed(decimals);
        return deg + "°" + min + "'" + sec + '"' + ew;
    }
});

// - Documentation: https://developers.google.com/maps/documentation/
app.directive("appMap", function () {
    return {
        restrict: "E",
        replace: true,
        template: "<div></div>",
        scope: {
            center: "=",        // Center point on the map (e.g. <code>{ latitude: 10, longitude: 10 }</code>).
            markers: "=",       // Array of map markers (e.g. <code>[{ lat: 10, lon: 10, name: "hello" }]</code>).
            width: "@",         // Map width in pixels.
            height: "@",        // Map height in pixels.
            zoom: "@",          // Zoom level (one is totally zoomed out, 25 is very much zoomed in).
            mapTypeId: "@",     // Type of tile to show on the map (roadmap, satellite, hybrid, terrain).
            panControl: "@",    // Whether to show a pan control on the map.
            zoomControl: "@",   // Whether to show a zoom control on the map.
            scaleControl: "@"   // Whether to show scale control on the map.
        },
        link: function (scope, element, attrs) {
            var toResize, toCenter;
            var map;
            var currentMarkers;

            // listen to changes in scope variables and update the control
            var arr = ["width", "height", "markers", "mapTypeId", "panControl", "zoomControl", "scaleControl"];
            for (var i = 0, cnt = arr.length; i < arr.length; i++) {
                scope.$watch(arr[i], function () {
                    cnt--;
                    if (cnt <= 0) {
                        updateControl();
                    }
                });
            }

            // update zoom and center without re-creating the map
            scope.$watch("zoom", function () {
                if (map && scope.zoom)
                    map.setZoom(scope.zoom * 1);
            });
            scope.$watch("center", function () {
                if (map && scope.center)
                    map.setCenter(getLocation(scope.center));
            });

            // update the control
            function updateControl() {

                // update size
                if (scope.width) element.width(scope.width);
                if (scope.height) element.height(scope.height);

                // get map options
                var options =
                {
                    center: new google.maps.LatLng(23, 79),
                    zoom: 6,
                    mapTypeId: "roadmap"
                };
                if (scope.center) options.center = getLocation(scope.center);
                if (scope.zoom) options.zoom = scope.zoom * 1;
                if (scope.mapTypeId) options.mapTypeId = scope.mapTypeId;
                if (scope.panControl) options.panControl = scope.panControl;
                if (scope.zoomControl) options.zoomControl = scope.zoomControl;
                if (scope.scaleControl) options.scaleControl = scope.scaleControl;

                // create the map
                map = new google.maps.Map(element[0], options);

                // update markers
                updateMarkers();

                // listen to changes in the center property and update the scope
                google.mapTypeIds.event.addListener(map, 'center_changed', function () {

                    // do not update while the user pans or zooms
                    if (toCenter) clearTimeout(toCenter);
                    toCenter = setTimeout(function () {
                        if (scope.center) {

                            // check if the center has really changed
                            if (map.center.lat() != scope.center.lat ||
                                map.center.lng() != scope.center.lon) {

                                // update the scope and apply the change
                                scope.center = { lat: map.center.lat(), lon: map.center.lng() };
                                if (!scope.$$phase) scope.$apply("center");
                            }
                        }
                    }, 500);
                });
            }

            // update map markers to match scope marker collection
            function updateMarkers() {
                if (map && scope.markers) {

                    // clear old markers
                    if (currentMarkers != null) {
                        for (var i = 0; i < currentMarkers.length; i++) {
                            currentMarkers[i] = m.setMap(null);
                        }
                    }

                    // create new markers
                    currentMarkers = [];
                    var markers = scope.markers;
                    if (angular.isString(markers)) markers = scope.$eval(scope.markers);
                    for (var i = 0; i < markers.length; i++) {
                        var m = markers[i];
                        var loc = new google.maps.LatLng(m.lat, m.lon);
                        var mm = new google.maps.Marker({ position: loc, map: map, title: m.name });
                        currentMarkers.push(mm);
                    }
                }
            }

            // convert current location to Google maps location
            function getLocation(loc) {
                if (loc == null) return new google.maps.LatLng(23, 79);
                if (angular.isString(loc)) loc = scope.$eval(loc);
                return new google.maps.LatLng(loc.lat, loc.lon);
            }
        }
    };
});


You can also find the code in : Google Drive

And can also check out for the video tutorial on : Youtube - Using Google Map Geolocation API with AngularJS

Google Maps



{{loc.lat | lat:0}}, {{loc.lon | lon:0}}

{{a.place}}: {{a.desc}}

No comments: