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;