Angularjs:Google Map Api - Google未定义

时间:2017-09-19 15:42:45

标签: javascript angularjs google-maps google-maps-api-3

我正在开发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的谷歌工厂:

(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);
        }
    }
})();

1 个答案:

答案 0 :(得分:0)

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

加载数据的时刻:

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

以及之后使用Geocoder时,没有保证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地图库在您的示例中以异步方式加载

,如下所示:

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 example