【问题标题】:Angularjs: Google Map Api - Google is not definedAngularjs:Google Map Api - Google 未定义
【发布时间】:2018-02-28 11:40:41
【问题描述】:

我正在开发一个 angularjs 单页应用程序,并且我正在尝试为该应用程序构建一个映射系统。地图加载正常,但是每当我尝试使用地理编码功能时,都会收到错误 referenceError: Google is not defined

地图控制器

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

【问题讨论】:

  • 我的角度不是很好,但通常你应该在 api 充满电后初始化你的地图,我在你的代码中看不到任何这种意义上的事情。

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


【解决方案1】:

显然,由于尚未加载 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);
        }
    }
})

然后可以通过 directivelink 函数像这样创建地图:

   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('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

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 2013-06-15
    • 2020-10-04
    • 2014-02-23
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    相关资源
    最近更新 更多