角度谷歌地图在初始地图加载后运行一次功能

angular-google-maps run function ONCE after initial map load

本文关键字:运行 功能 一次 加载 谷歌地图 地图      更新时间:2023-09-26

使用角度谷歌地图将谷歌地图合并到应用程序中

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

我不能使用idletilesloaded因为它们是在每次动作后发射的......

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

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

我尝试将maps.getBounds()放入第二个 promise 函数中,但它不起作用。

请注意,我在这里有一个小提琴 - 在定义$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...
    });
});

显然,uiGmapGoogleMapApi promise 返回的maps对象与 tilesloaded 等事件返回的maps对象完全不同...... 相当令人困惑。

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

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

有了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);
    };
});

斯菲德尔


。不知道为什么常见问题解答中没有提到这一点:"如何访问地图实例?"-或者为什么建议使用tilesloaded(被认为不可靠)而不是idleuiGmapIsReady......?
也许常见问题解答问题实际上是"如何持续访问地图"?


正如

Sal Niro在另一个答案中指出的那样 - 绕过不断调用tilesloadedidle的一种选择是定义一个变量,然后在第一次运行events函数时将其标记为 true。

有点

黑客和令人惊讶的是,API 在从控制器内初始地图加载后没有办法访问地图对象......但它有效。

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

解决方案
定义一个设置为false0的变量(此处任意称为"initialMapLoad"):
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 中的工作示例