6

使用angular-google-maps将谷歌地图合并到应用程序中

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

我不能使用idle,或者tilesloaded因为这些在每次动作后都会被解雇......

我要运行的功能需要获取地图边界以在初始页面加载时从服务器中提取数据 - 我希望这在初始加载时发生一次,然后是使用刷新的手动功能map-control
- 如果我使用idletilesloaded触发它,它将每次用户移动地图时拉取服务器数据。

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

我试过maps.getBounds()加入第二个承诺功能,但它不起作用。

请注意,我在这里有一个小提琴- 在定义控件/选项等之后,我不能再链接任何承诺,$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...
    });
});

显然, promisemaps返回的对象与诸如 etc 之类的事件返回uiGmapGoogleMapApi的对象完全不同……相当混乱。 mapstilesloaded

此外,FAQ仅指示如何使用tilesloaded来获取地图实例 - 由于已经描述的原因,这不起作用。

4

2 回答 2

9

我认为“正确”的方法是通过将服务注入控制器来使用 APIIsReady功能。uiGmapIsReady请参阅文档

有了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


...不知道为什么FAQ中没有提到这一点:'我如何访问地图实例?' - 或者为什么建议使用tilesloaded被认为是不可靠的)而不是idleor uiGmapIsReady...?
也许常见问题解答问题真的是'我如何持续访问地图'?


于 2015-02-03T07:05:21.920 回答
1

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

在从控制器内部加载初始地图后,API 无法访问地图对象,这有点骇人听闻和令人惊讶……但它可以工作。

但是- 添加这个答案,因为将整个控制器放在一个函数(或条件)中是不切实际的 - 并且您可能希望连续调用一些函数。因此,只需在调用地图之前在控制器中定义“运行一次”变量即可。

解决方案
定义一个变量(这里任意称为“initialMapLoad”)设置为false0
var initialMapLoad = 0

然后,在您的谷歌地图事件定义(例如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;
                    }
                },
            }
        };
    })
});

在这个 jsfiddle中查看一个工作示例

于 2015-02-01T05:24:02.123 回答