angular-google-maps在初始地图加载后运行函数ONCE

时间:2015-01-31 01:38:06

标签: javascript angularjs google-maps angular-google-maps

使用angular-google-maps将Google地图合并到应用

我需要一个在初始地图加载完成后运行函数ONCE的命令 - 但仅限于初始加载, 不是在每次地图操作之后

我无法使用idletilesloaded,因为这些都会在每次移动后被解雇......

我想要运行的函数需要获取映射边界,以便在初始页面加载时从服务器中提取数据 - 我希望这在初始加载时发生,然后是使用刷新map-control的手动功能 - 如果我使用idletilesloaded来启动此操作,则会在用户移动地图的每个时间内提取服务器数据

有没有人知道如何在初始地图加载后触发一次性命令以获取地图详细信息(边界等)?

我已经尝试将maps.getBounds()放在第二个承诺函数中,但它不起作用。

注意,I've got a fiddle working here - 在定义$scope.map控件/选项等之后,我无法将更多的承诺链接起来,因为它们不会返回承诺:

文档中的代码示例并未显示如何在 $scope.map定义后链接承诺

HTML

<div class="angular-google-map-container" ng-controller="MainCtrl">
    <ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="map.options" events="map.events" control="googlemap">
    </ui-gmap-google-map>
</div>

控制器

myApp.controller('MainCtrl', function($scope, uiGmapGoogleMapApi) {
    uiGmapGoogleMapApi
    .then(function(maps){
        $scope.map = {
            center: {
                latitude: 37.7749295, 
                longitude: -122.4194155 
            },
            zoom: 12
            events: {
                tilesloaded: function (maps, eventName, args) {
                    myServiceFuntion(maps)    // this work fine but fires every time
                },
                dragend: function (maps, eventName, args) {
                    myServiceFuntion(maps)    // this work fine but fires every time
                },
                zoom_changed: function (maps, eventName, args) {
                    myServiceFuntion(maps)    // this work fine but fires every time
                }
            }
        }

        $scope.bounds = maps.getBounds()    // this gives me 'getBounds() not a function'
        myServiceFuntion(maps);    // this gives an error... ?
        return maps;            //no promise returned here so no chance to delay the function below
    })
    .then(function(maps){
        //is this where i need to put my function ?  doesn't delay on map load since no promise returned...
    });
});

显然,maps承诺返回的uiGmapGoogleMapApi对象与maps等事件返回的tilesloaded对象完全不同......非常令人困惑。

此外,the FAQ仅指示如何使用tilesloaded来获取地图实例 - 由于已经描述的原因,该实例无法正常工作。

2 个答案:

答案 0 :(得分:9)

我认为“正确”的方法是通过将IsReady服务注入控制器来使用API​​ uiGmapIsReady功能。请参阅the documentation

使用uiGmapIsReady承诺,然后可以将map传递给函数/服务等,代码如下:

uiGmapIsReady.promise()                     // this gets all (ready) map instances - defaults to 1 for the first map
.then(function(instances) {                 // instances is an array object
    var maps = instances[0].map;            // if only 1 map it's found at index 0 of array
    $scope.myOnceOnlyFunction(maps);        // pass the map to your function
});

也可以遍历instances数组来运行每个地图上的函数(如果你的页面中加载了多个地图):

uiGmapIsReady.promise()                     // this gets all (ready) map instances - defaults to 1 for the first map
.then(function(instances) {                 // instances is an array object
    angular.forEach(instances, function(value, key) {
        var maps = value.map;
        $scope.myOnceOnlyFunction(maps);    // will apply this function to each map
    });
});

所以整个控制器看起来像

myApp.controller('MainCtrl', function($scope, uiGmapGoogleMapApi, uiGmapIsReady) {
    uiGmapGoogleMapApi
    .then(function(maps){
        $scope.googlemap = {};
        $scope.map = {
            center: {
                latitude: 37.7749295, 
                longitude: -122.4194155 
            },
            zoom: 13,
            pan: 1,
            options: myAppServices.getMapOptions().mapOptions,
            control: {},
            events: {
                tilesloaded: function (maps, eventName, args) {
                },
                dragend: function (maps, eventName, args) {
                },
                zoom_changed: function (maps, eventName, args) {
                }
            }
        };
    });

    uiGmapIsReady.promise()                     // this gets all (ready) map instances - defaults to 1 for the first map
    .then(function(instances) {                 // instances is an array object
        var maps = instances[0].map;            // if only 1 map it's found at index 0 of array
        $scope.myOnceOnlyFunction(maps);        // this function will only be applied on initial map load (once ready)
    });

    $scope.myOnceOnlyFunction = function(maps){  // this will only be run once on initial load
        var center = maps.getCenter();           // examples of 'map' manipulation
        var lat = center.lat();
        var lng = center.lng();
        alert('I\'ll only say this once ! \n Lat : ' + lat + '\n Lng : ' + lng);
    };
});

jsfiddle


...不确定为什么常见问题解答中没有提及:'How do I access the map instance?' - 或者为什么建议使用tilesloadedwhich is thought to be unreliable)代替idleuiGmapIsReady ......? 也许FAQ问题真的是“ 我如何持续访问地图 ”?


答案 1 :(得分:1)

正如Sal Niro指出另一个答案 - 绕过常量调用tilesloadedidle的一个选项是定义一个变量,然后在第一次将其标记为真时events个函数运行。

在控制器内初始地图加载后,API没有方法可以访问地图对象,这有点神奇和令人惊讶......但它确实有效。

然而 - 添加此答案,因为将整个控制器置于某个功能(或条件)中是不切实际的 - 并且您可能有一些功能想要被连续召唤。因此,只需定义一次&#39;运行一次&#39;在调用地图之前,在控制器中变量

<强>解决方案
将变量(此处任意称为&#34; initialMapLoad&#34;)设置为false0
var initialMapLoad = 0

然后,在您的Google地图事件定义(例如tilesloadeddragendidle)中,您可以在条件内放置您只想运行一次的函数:

if(initialMapLoad === 0) { 
    my_single_run_function(); 
    var initialMapLoad = 1
}

在您的功能运行后,不要忘记将initialMapLoad变量重新定义为1true

示例:

myApp.controller('MainCtrl', function($scope, uiGmapGoogleMapApi) {

    var initialMapLoad = 0;

    uiGmapGoogleMapApi
    .then(function(maps){
        $scope.map = {
            center: {
                latitude: 37.7749295, 
                longitude: -122.4194155 
            },
            zoom: 13,
            events: {
                tilesloaded: function (maps, eventName, args) {
                    // functions that run every time 
                    alert('I say this after every tile load');

                    if(initialMapLoad === 0){
                        // functions that run only once
                        alert('I only say this once' + maps.getBounds());
                        initialMapLoad = 1;
                    }
                },
            }
        };
    })
});

请参阅this jsfiddle

中的工作示例