5

现在我已经在这个SO initialize-google-map-in-angularjsAndy Joslin的帮助下找到了初始化Google地图的方法,我正在寻找一种异步加载Google Map对象的方法。如何在AngularJS中异步加载谷歌地图?

我找到了一个在phonecat项目中如何做到这一点的例子。

通知的JS文件是如何在这个例子中加载:index-async.html

在我玉脚本部分加载到我的节目,我试过:

script(src='js/lib/angular/angular.js') 
script(src='js/lib/script/script.min.js') 

script 
    $script([ 
    'js/lib/angular/angular-resource.min.js', 
    'js/lib/jquery/jquery-1.7.2.min.js', 
    'http://maps.googleapis.com/maps/api/js?key=AIzaSyBTmi_pcXMZtLX5MWFRQgbVEYx-h-pDXO4&sensor=false', 
    'js/app.js', 
    'js/services.js', 
    'js/controllers.js', 
    'js/filters.js', 
    'js/directives.js', 
    'bootstrap/js/bootstrap.min.js' 
    ], function() { 
     // when all is done, execute bootstrap angular application 
     angular.bootstrap(document, ['ofm']); 
    }); 

当我做到这一点,去加载地图页面,我得到:

A call to document.write() from an asycrononously-loaded 
external script was ignored. 

这是怎么了谷歌地图现在正在加载为服务:

'use strict'; 

var app = angular.module('ofm.services', []); 

app.factory('GoogleMaps', function() { 

    var map_id = '#map'; 
    var lat  = 46.87916; 
    var lng  = -3.32910; 
    var zoom = 15; 
    var map  = initialize(map_id, lat, lng, zoom); 

    return map; 
}); 

function initialize(map_id, lat, lng, zoom) { 
    var myOptions = { 
    zoom : 8, 
    center : new google.maps.LatLng(lat, lng), 
    mapTypeId : google.maps.MapTypeId.ROADMAP 
    }; 
    return new google.maps.Map($(map_id)[0], myOptions); 
} 

看起来,这应该是从我记得读到的回报承诺。但是这个AngularJS对我来说是非常新的。

+0

要促进这方面的进展我在这里创建了一个git项目:https://github.com/LarryEitel/angular-google-maps并推动它在这里生活:http://angular-google-maps.nodester.com/。我在此处启动了Google Groups中的一个主题:https://groups.google.com/forum/?fromgroups&nomobile=true#!topic/angular/CM8ewcWeTF4 –

+0

当您异步加载Maps API库时,您必须*提供使用'callback ='查询参数的回调函数。否则,API加载器将使用'document.write()',它不会从异步调用中工作。 [GFoley83](http://stackoverflow.com/a/17396353/1202830)中的迷你库的答案为您添加了此参数,这就是为什么它可以在异步加载情况下工作的原因。 –

回答

5

如果您在AngularJS应用程序使用jQuery,看看这个函数返回时,谷歌地图API已经加载了promise

https://gist.github.com/gbakernet/828536

我能够在AngularJS指令使用按需延迟加载Google地图。 作品一种享受:

angular.module('mapModule') // usage: data-google-map 
    .directive('googleMap', ['$window', function ($window) { 
     return { 
      restrict: 'A', 
      link: function (scope, element, attrs) { 
       // If Google maps is already present then just initialise my map 
       if ($window.google && $window.google.maps) { 
        initGoogleMaps(); 
       } else { 
        loadGoogleMapsAsync(); 
       } 

       function loadGoogleMapsAsync() { 
        // loadGoogleMaps() == jQuery function from https://gist.github.com/gbakernet/828536 
        $.when(loadGoogleMaps()) 
         // When Google maps is loaded, add InfoBox - this is optional 
         .then(function() { 
          $.ajax({ url: "/resources/js/infobox.min.js", dataType: "script", async: false }); 
         }) 
         .done(function() { 
          initGoogleMaps(); 
         }); 
       }; 

       function initGoogleMaps() { 
        // Load your Google map stuff here 
        // Remember to wrap scope variables inside `scope.$apply(function(){...});` 
       } 
      } 
     }; 
    }]); 
+9

Eek,混合Angular和jQuery! –

+1

@甜菜根 - 甜菜根打你的屁股我做到了!目前,使用AngularJS加载脚本并不容易,Google Maps API本身不支持承诺。我提出了一个比较适当的解决方案;如果你有更好的一个,那么让我们看看它! :) – GFoley83

+0

GFoley,我明白你的观点,我没有说这不合理,我只是说“eek”。我没有尝试过,但是AngularJS的$ q不会强制jQuery根据Q.js承诺它自己?如果是这样,那么在'loadGoogleMapsAsync()'中,除了'$ .ajax(...)'表达式之外的所有表达式都可以用$ q编写,这在Angular.js模块中更合适。 –

7

,这里是我的解决方案,我想出了不使用jQuery: (Gist here

angular.module('testApp', []). 
    directive('lazyLoad', ['$window', '$q', function ($window, $q) { 
     function load_script() { 
      var s = document.createElement('script'); // use global document since Angular's $document is weak 
      s.src = 'https://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize'; 
      document.body.appendChild(s); 
     } 
     function lazyLoadApi(key) { 
      var deferred = $q.defer(); 
      $window.initialize = function() { 
       deferred.resolve(); 
      }; 
      // thanks to Emil Stenström: http://friendlybit.com/js/lazy-loading-asyncronous-javascript/ 
      if ($window.attachEvent) { 
       $window.attachEvent('onload', load_script); 
      } else { 
       $window.addEventListener('load', load_script, false); 
      } 
      return deferred.promise; 
     } 
     return { 
      restrict: 'E', 
      link: function (scope, element, attrs) { // function content is optional 
      // in this example, it shows how and when the promises are resolved 
       if ($window.google && $window.google.maps) { 
        console.log('gmaps already loaded'); 
       } else { 
        lazyLoadApi().then(function() { 
         console.log('promise resolved'); 
         if ($window.google && $window.google.maps) { 
          console.log('gmaps loaded'); 
         } else { 
          console.log('gmaps not loaded'); 
         } 
        }, function() { 
         console.log('promise rejected'); 
        }); 
       } 
      } 
     }; 
    }]); 
2

看看这个我认为它更可靠

var deferred = $q.defer(); 
         var script = document.createElement('script'); 

         $window.initMap = function() { 
          //console.log("Map init "); 

          deferred.resolve(); 
         } 
         script.src = "//maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&callback=initMap"; 
         document.body.appendChild(script); 
         return deferred.promise;