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

可紊 提交于 2019-12-04 06:42:41
goredwards

The 'correct' method I believe is to use the API IsReady feature by injecting the uiGmapIsReady service into the controller. See the documentation.

With the uiGmapIsReady promise it's then possible to pass the map to a function / service etc with code like:

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

it's also possible to iterate through the instances array to run functions on each map (if you have more than one map loaded in your page):

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

so then the whole controller would look like

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


...not sure why this isn't mentioned in the FAQ: 'How do I access the map instance?' - or why using tilesloaded (which is thought to be unreliable) is suggested instead of idle or uiGmapIsReady... ?
Perhaps the FAQ question was really 'how do i access the map on a continual basis' ?


As Sal Niro point out in another answer - one option to get around the constant calling of tilesloaded or idle is to define a variable and then mark it as true the first time the events functions run.

It's a bit hackish and surprising that the API has no method to access the maps object after initial map load from within the controller ...but it works.

However - adding this answer since it's not practical to put your entire controller within a function (or condition) - and there are some functions you may want to be called continuously. So simply define the 'run once' variable within your controller prior to your map being called.

Solution:
Define a variable (here arbitrarily called "initialMapLoad") set to false or 0 :
var initialMapLoad = 0

Then, within your google maps events definition (such as tilesloaded, dragend or idle) you can put the functions you only want to run once, within a conditional :

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

Don't forget to redefine the initialMapLoad variable to 1 or true once your function runs.

Example:

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;
                    }
                },
            }
        };
    })
});

See a working example in this jsfiddle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!