AngularJS-załaduj skrypt google map async w dyrektywie dla wielu map
Obecnie próbuję załadować wiele map google na jednej stronie. Nie chcę dołączać skryptu google map API do kodu HTML, ponieważ nie chcę, aby skrypt był ładowany, chyba że mapy są na bieżącej stronie. Chcę, aby Moje mapy były wywoływane wewnątrz jednej dyrektywy, która będzie również wykonywać skrypt google map API leniwe Ładowanie.
Więc szukałem i znalazłem rozwiązanie , które trochę poprawiłem, ale mój problem polega na tym, że załaduje tylko jedną mapę, ale nie i inni
Mój HTML wygląda tak:
<div id="mapParis" class="google-map" lat="48.833" long="2.333"></div>
<div id="mapWashington" class="google-map" lat="38.917" long="-77.000"></div>
<div id="mapTokyo" class="google-map" lat="35.667" long="139.750"></div>
I dyrektywa:
// Google Map
app.directive('googleMap', ['$window', '$q', function( $window, $q ) {
function loadScript() {
console.log('loadScript');
// use global document since Angular's $document is weak
var s = document.createElement('script');
s.src = '//maps.googleapis.com/maps/api/js?sensor=false&language=en&callback=initMap';
document.body.appendChild(s);
}
// Lazy loading of the script
function lazyLoadApi(key) {
console.log('lazyLoadApi');
var deferred = $q.defer();
$window.initMap = function () {
deferred.resolve();
};
if ( $window.attachEvent ) {
$window.attachEvent('onload', loadScript);
} else {
$window.addEventListener('load', loadScript, false);
}
return deferred.promise;
}
return {
restrict: 'C', // restrict by class name
scope: {
mapId: '@id', // map ID
lat: '@', // latitude
long: '@' // longitude
},
link: function($scope, elem, attrs) {
// Check if latitude and longitude are specified
if ( angular.isDefined($scope.lat) && angular.isDefined($scope.long) ) {
console.log('-----');
// Initialize the map
$scope.initialize = function() {
console.log($scope.mapId);
$scope.location = new google.maps.LatLng($scope.lat, $scope.long);
$scope.mapOptions = {
zoom: 6,
center: $scope.location
};
$scope.map = new google.maps.Map(document.getElementById($scope.mapId), $scope.mapOptions);
new google.maps.Marker({
position: $scope.location,
map: $scope.map,
});
}
// Check if google map API is ready to run
if ( $window.google && $window.google.maps ) {
console.log('gmaps already loaded');
// Google map already loaded
$scope.initialize();
} else {
lazyLoadApi().then(function () {
// Promised resolved
console.log('promise resolved');
if ( $window.google && $window.google.maps ) {
// Google map loaded
console.log('gmaps loaded');
$scope.initialize();
} else {
// Google map NOT loaded
console.log('gmaps not loaded');
}
}, function () {
// Promise rejected
console.log('promise rejected');
});
}
}
}
};
Tutaj jest jsFiddle z 3 mapami, zobaczysz, że tylko ostatnia jest załadowana:
http://jsfiddle.net/5Pk8f/1/
Myślę, że robię coś nie tak z moim zakresem lub sposobem, w jaki obietnica jest obsługiwana, ale na razie nie mam pomysłów...
Dzięki! (i sorry for my not that good english)Update (po odpowiedzi)
Jako aktualizacja,
oto pełne rozwiązanie, które wymyśliłem:
http://plnkr.co/edit/1NpquJ?p=preview (@maurycy plunker)
Google map service
// Lazy loading of Google Map API
app.service('loadGoogleMapAPI', ['$window', '$q',
function ( $window, $q ) {
var deferred = $q.defer();
// Load Google map API script
function loadScript() {
// Use global document since Angular's $document is weak
var script = document.createElement('script');
script.src = '//maps.googleapis.com/maps/api/js?sensor=false&language=en&callback=initMap';
document.body.appendChild(script);
}
// Script loaded callback, send resolve
$window.initMap = function () {
deferred.resolve();
}
loadScript();
return deferred.promise;
}]);
Dyrektywa Google map
// Google Map
app.directive('googleMap', ['$rootScope', 'loadGoogleMapAPI',
function( $rootScope, loadGoogleMapAPI ) {
return {
restrict: 'C', // restrict by class name
scope: {
mapId: '@id', // map ID
lat: '@', // latitude
long: '@' // longitude
},
link: function( $scope, elem, attrs ) {
// Check if latitude and longitude are specified
if ( angular.isDefined($scope.lat) && angular.isDefined($scope.long) ) {
// Initialize the map
$scope.initialize = function() {
$scope.location = new google.maps.LatLng($scope.lat, $scope.long);
$scope.mapOptions = {
zoom: 12,
center: $scope.location
};
$scope.map = new google.maps.Map(document.getElementById($scope.mapId), $scope.mapOptions);
new google.maps.Marker({
position: $scope.location,
map: $scope.map,
});
}
// Loads google map script
loadGoogleMapAPI.then(function () {
// Promised resolved
$scope.initialize();
}, function () {
// Promise rejected
});
}
}
};
}]);
Przykład użycia HTML
<div id="mapParis" class="google-map" lat="48.833" long="2.333"></div>
<div id="mapWashington" class="google-map" lat="38.917" long="-77.000"></div>
<div id="mapTokyo" class="google-map" lat="35.667" long="139.750"></div>
Jeszcze raz podziękowania dla Maurycego
1 answers
Masz tu problem z obietnicami i inicjalizacją, zrobiłem to czystszym dla ciebie
Najwyraźniej jsfiddle został usunięty więc tutaj działa plunker: http://plnkr.co/edit/1NpquJ?p=preview
Js
Oto serwis dla leniwych ładowań gmapów
app.service('lazyLoadApi', function lazyLoadApi($window, $q) {
function loadScript() {
console.log('loadScript')
// use global document since Angular's $document is weak
var s = document.createElement('script')
s.src = '//maps.googleapis.com/maps/api/js?sensor=false&language=en&callback=initMap'
document.body.appendChild(s)
}
var deferred = $q.defer()
$window.initMap = function () {
deferred.resolve()
}
if ($window.attachEvent) {
$window.attachEvent('onload', loadScript)
} else {
$window.addEventListener('load', loadScript, false)
}
return deferred.promise
});
Wtedy dyrektywa robi to co powinna, działa tylko z map, nie ładuje plików js na żadnej innej logice
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-29 15:43:57