Angularjs: Google Map Api - Google is not defined



我正在研究AngularJS单页应用程序,并且我正在尝试为应用程序构建映射系统。该地图的加载正常,但是每当我尝试使用地理编码功能时,我都会得到错误 ReferenceError:Google未定义

地图控制器

(function () {
    'use strict';
    angular
        .module('CityWits')
        .controller('mapCtrl', mapCtrl);
    mapCtrl.$inject = ['$scope', '$http', 'mapApi', '$q'];
    function mapCtrl($scope, $http, mapApi, $q){
        var vm = this;
        vm.setQuery = setQuery;
        // todo: Switch this out with deals that are loaded depending on the radius of the map

        getBranches();
        function setQuery(query) {
            console.log("business deal filter controller : query=" + query);
            vm.query = query;
            vm.focus = false;
        }
        function getBranches(){
            $http.get('app/cwitsTestData/branchData.json').then(function(data){
                vm.branches = sortBranches(data.data.branches);
                $scope.$broadcast("branchesSorted", vm.branches);
            });
        }
    }
    function sortBranches(branches){
        var locations, address, text;
        locations = [];
        for(var branch in branches){
            address = branches[branch].address;
            text = address.street_line1 + " " + address.city+ " " +address.state;
            locations.push(text);
        }
        return locations;
    }
})();

这是我写的用于处理API的Google工厂:

(function() {
    'use strict';
    angular
        .module('CityWits')
        .factory('mapApi', mapApi);

    function mapApi () {
        var mapApi = {}
        var markers = [];
        var geocoder;
        var service;

        mapApi.geocode = geocode;
        mapApi.marker = marker;
        mapApi.distance = distance;
        return mapApi;
        function geocode (addresses){
            geocoder = new google.maps.Geocoder();
            var coords = [];
            if(geocoder){
                for(var i in addresses){
                    geocoder.geocode( { 'address': addresses[i]}, function(results, status) {
                          if (status === 'OK') {
                            coords.push(results[0].geometry.location);
                          } else {
                            alert('Geocode was not successful for the following reason: ' + status);
                          }
                    });
                }
            }
        }
        function distance(start, end, method="DRIVING"){
            service = new google.maps.DistanceMatrixService;
            service.getDistanceMatrix({
                origins: start,
                destinations: end,
                travelMode: method
            }, function (status, response){
                if(status ==! "OK"){
                    console.log("Error: "+status);
                } else {
                    console.log("distance measured");
                    var result = {};
                    for(var i in response.rows){
                        result = response.rows[i].element;
                    }
                    return result;
                }
            });
        }
        function marker(positions, json){
            if(markers.length > 0){
                for(o in markers){
                    markers[o].setMap(null);
                }
            }
            for(x in positions){
            }
        }
    }

})();

最后,这是启动API的指令:

(function () {
    'use strict';
    angular
        .module('CityWits')
        .directive('dealMap', dealMap);
    dealMap.$inject = ['$timeout', '$http', 'mapApi'];
    function dealMap($timeout, $http, mapApi){
        var directive = {
            link: link,
            templateUrl: 'app/map/map.directive.html',
            scope: {
                deals: '=',
                branches: '='
            },
            restrict: 'EA'
        };
        return directive;
        function link(scope, element, attrs) {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.async = true;
            script.defer = true;
            script.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyB4RaOArTNm9C7crfutMVc0KkWIoQG-ZE0";
            document.body.appendChild(script);
            $timeout(function(){
                scope.initialize();
            }, 500);
            // todo: Do stuff after deals are loaded based on map radius
            scope.$on('branchesSorted', function(event, data) {
                console.log('deals loaded');
                console.log(data);
                var points = mapApi.geocode(data);
                console.log(points);
            });
            scope.initialize = function() {
                scope.mapOptions = {
                    zoom: 8,
                    center: new google.maps.LatLng(22.649907498685803, 88.36255413913727)
                };
                scope.map = new google.maps.Map(document.getElementById('map'), scope.mapOptions);
            };
            console.log(scope);
        }
    }
})();

显然发生此错误,因为尚未加载Google Maps API。

数据加载的时刻:

$http.get('app/cwitsTestData/branchData.json').then(function(data){
      vm.branches = sortBranches(data.data.branches);
      $scope.$broadcast("branchesSorted", vm.branches);
});

之后,一旦使用了Geocoder,就会有 no 任何保证Google Maps API当时已加载:

scope.$on('branchesSorted', function(event, data) {
            console.log('deals loaded');
            console.log(data);
            var points = mapApi.geocode(data);   //<--Google Maps API could be still not loaded at that moment
            console.log(points);
        });

由于Google Maps库已加载异步在您的示例中:

var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
script.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyB4RaOArTNm9C7crfutMVc0KkWIoQG-ZE0";
document.body.appendChild(script);

我将建议提出以下解决方案。

让我们介绍以下服务以加载Google Maps API,创建地图并在准备就绪后通知:

  .factory('googleMapsApi', function ($rootScope,$window, $q) {
    return {
        load: function (key) {
            var deferred = $q.defer()
            if ($window.google && $window.google.maps) {
                deferred.resolve($window.google);
            }
            else {
                    var url = 'https://maps.googleapis.com/maps/api/js?callback=googleMapsLoad';
                    if (key) url += "&key=" + key;
                    var script = document.createElement('script');
                    script.type = 'text/javascript'
                    script.src = url;
                    $window.googleMapsLoad = function () {
                        deferred.resolve($window.google);
                    }
                    document.body.appendChild(script);
            }
            return deferred.promise;
        },
        createMap : function(scope,id,options){
             var mapObject = new google.maps.Map(document.getElementById(id), options);  
             scope.$emit('google-maps-loaded',mapObject);
        },
        onMapReady : function(scope, ready){
            var handler = $rootScope.$on('google-maps-loaded', function(evnt,data){ return ready(data);});
            scope.$on('$destroy', handler);
        }
    }
})

然后可以通过指令的link函数这样创建地图

   link: function (scope, element, attributes) {
            googleMapsApi.load(scope.key)
            .then(function () {
                var mapOptions = {
                    center: scope.center,
                    zoom: scope.zoom,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                };
                googleMapsApi.createMap(scope,attributes.id,mapOptions);
            });
        }

和数据在 Controller 中加载:

.controller('MyCtrl', function ($scope, googleMapsApi) {
    googleMapsApi.onMapReady($scope, function(mapInst) {
         console.log('Google Map is ready');
         mapInst.data.loadGeoJson('https://storage.googleapis.com/mapsdevsite/json/google.json');
    });
});

jsfiddle示例

最新更新