319

I’m embedding Google Maps into my web site. Once Google Maps is loaded, I need to kick off a few JavaScript processes.

Is there a way to auto-detect when Google Maps has fully loaded, including tile downloads and all?

A tilesloaded() method exists that is supposed to accomplish exactly this task but it does not work.

TRiG
  • 10,148
  • 7
  • 57
  • 107
  • 2
    The "tilesloaded" event seems to work for me. It fires when the page loads and when I move the map around. On your map, is it just inconsistent, or does it never work? – Chris B May 07 '09 at 15:38
  • 1
    No, just no. "tilesloaded" as it says will be fired every time new tiles are loaded which means it will not only fire on first load also but also every time you drag map to location where your tiles haven't been loaded yet. – Aivus Feb 08 '19 at 12:42
  • Depends if you use addListener() or addListenerOnce(). You are right about addListener() - thats why I use `google.maps.event.addListenerOnce(map, 'tilesloaded', function() {` – Christoph Lösch Jan 06 '20 at 15:29

13 Answers13

637

This was bothering me for a while with GMaps v3.

I found a way to do it like this:

google.maps.event.addListenerOnce(map, 'idle', function(){
    // do something only the first time the map is loaded
});

The "idle" event is triggered when the map goes to idle state - everything loaded (or failed to load). I found it to be more reliable then tilesloaded/bounds_changed and using addListenerOnce method the code in the closure is executed the first time "idle" is fired and then the event is detached.

See also the events section in the Google Maps Reference.

hitautodestruct
  • 20,081
  • 13
  • 69
  • 93
ddinchev
  • 33,683
  • 28
  • 88
  • 133
  • so this fires when it failed to load as well? I really need to ensure that everything loaded, is there anyway to test that..? – williamsandonz Jan 23 '12 at 21:50
  • 15
    It is fired when the map goes to idle state (nothing more will load). Sometimes there might be some tiles that didn't load because of bad connection so even if there are such missing pieces, it will trigger the idle event in the end. If you need to ensure that the map is complete, no missing tiles, etc, you should seek some other way (for example "tilesloaded" event). – ddinchev Jan 24 '12 at 17:00
  • I did switch to this a while back too since it was more reliable, but I'm still noticing, on occasion, that it fires before all the tiles are loaded. – johntrepreneur Mar 10 '13 at 21:11
  • Yes but then it means they will not be loaded anyway (at least if you don't "jiggle" the map a bit). – ddinchev Mar 10 '13 at 21:30
  • 17
    it is not working for me.. triggers before anything shows up on my map – zsitro May 26 '13 at 14:49
  • 17
    -1: Triggers sooner than tiles are loaded/displayed. – zbr Dec 27 '13 at 22:59
  • Maybe, can not confirm that. But as far as I remember, the tiles loaded/displayed events weren't very reliable - e.g. if they fail to load sometimes, the event would not fire up. It should be noted that back then the version of GMaps v3 was quite earlier. – ddinchev Dec 29 '13 at 15:35
  • Brilliant solution. I had the problem that I needed `getProjection` to be filled - this solution rocks it. – Niels Keurentjes Feb 20 '14 at 16:49
  • This does work as @Veseliq explained, however the 'idle' event firing does not mean that your map is also visible. You have to determine that for yourself. – Alex Mar 05 '14 at 19:47
  • 12
    -1: for me in chrome and firefox, it consistently fires as soon as the script has loaded but before any tile shows. Maybe it's not apparent on a fast connection, but I am blessed with a very slow one. 'tilesloaded' seems to work though. – Xananax Jun 24 '14 at 13:46
  • excellent solution, i successfully update overlay that overlap using idle event. – Dika Arta Karunia Oct 30 '15 at 07:39
  • I know it's old but i need something like this nowadays, however I'm not using any IP on my code or scripts, just embedding the map withiun an iFrame using the option that GMaps gives. – DJ22T Nov 04 '15 at 20:14
  • 2
    Thanks for that solution - I think this is exactly what I needed. What I simply cannot wrap my head around, is why on earth google haven't put in a simple ready hook? :-O – hasse Jun 14 '16 at 11:02
  • What is "`map`"? A reference to `$('#mapBox');` where `mapBox` is a `
    `?
    – Olivier Pons Nov 20 '16 at 21:24
  • Not at all the right answer. My answer explain how to do that. It is well documented from Google. – Andrea Turri Dec 19 '16 at 12:41
  • As @ddinchev says, this event fires whether everything loaded or not. For my use case, that was better than "tilesloaded". I needed to fire a "resize" event as soon as the map had loaded and "tilesloaded" was not working in IE. "idle" worked because it fired regardless of the tiles being loaded or not. – Tasos Feb 10 '17 at 11:05
67

I'm creating html5 mobile apps and I noticed that the idle, bounds_changed and tilesloaded events fire when the map object is created and rendered (even if it is not visible).

To make my map run code when it is shown for the first time I did the following:

google.maps.event.addListenerOnce(map, 'tilesloaded', function(){
    //this part runs when the mapobject is created and rendered
    google.maps.event.addListenerOnce(map, 'tilesloaded', function(){
        //this part runs when the mapobject shown for the first time
    });
});
Pyry Liukas
  • 431
  • 6
  • 10
  • 5
    The first tilesloaded function works well for me, but the second tilesloaded function never runs for me. – Goose Dec 28 '15 at 19:33
  • I'm getting `Uncaught ReferenceError: map is not defined`. I've tried running the script with a delay and at the end of my other scripts but nothing seems to work. – Sam Willis Mar 30 '16 at 08:50
  • 1
    if you're defining event handlers inside event handlers, you're going to have a bad time. i would strongly suggest you don't do this, here's a slightly less hacky alternative that achieves a similar thing: https://gist.github.com/cmawhorter/a1b0b6a6b73678b97920f748ebca244b – Cory Mawhorter Jun 15 '16 at 01:10
  • @SamWillis That was most likely because your `map` object was not instantiated, I know you said you added it at the end but thats what the error means...that it cant find your map object – Uriahs Victor Nov 06 '21 at 14:33
24

In 2018:

var map = new google.maps.Map(...)
map.addListener('tilesloaded', function () { ... })

https://developers.google.com/maps/documentation/javascript/events

haffla
  • 1,056
  • 8
  • 15
  • tilesloaded is the only solution that correctly waits until KML layers have all rendered – smirkingman Jan 31 '20 at 15:16
  • 1
    This worked for me but It fired everytime I manipulated the map, in the end I had to use `google.maps.event.addListenerOnce(map, 'tilesloaded', function(){}` so that i can get it to only fire once. `addListenerOnce` doesn't seem to be supported on `map` – Uriahs Victor Nov 06 '21 at 14:35
16

If you're using the Maps API v3, this has changed.

In version 3, you essentially want to set up a listener for the bounds_changed event, which will trigger upon map load. Once that has triggered, remove the listener as you don't want to be informed every time the viewport bounds change.

This may change in the future as the V3 API is evolving :-)

Alexander
  • 23,432
  • 11
  • 63
  • 73
timbo
  • 13,244
  • 8
  • 51
  • 71
  • 2
    I'm not finding this working for me as reliably as looking for the `tilesloaded` event. – TMC Jul 02 '12 at 06:19
7

If you're using web components, then they have this as an example:

map.addEventListener('google-map-ready', function(e) {
   alert('Map loaded!');
});
Phillip Senn
  • 46,771
  • 90
  • 257
  • 373
5

GMap2::tilesloaded() would be the event you're looking for.

See GMap2.tilesloaded for references.

Alexander
  • 23,432
  • 11
  • 63
  • 73
Adam Markowitz
  • 12,919
  • 3
  • 29
  • 21
  • I've read a lot about the tilesloaded() event and it seems that it is extremely inconsistent on when it fires. Any other options? –  May 07 '09 at 03:20
3

Where the variable map is an object of type GMap2:

    GEvent.addListener(map, "tilesloaded", function() {
      console.log("Map is fully loaded");
    });
devlord
  • 4,054
  • 4
  • 37
  • 55
1

For Google Maps V3, to check when google maps is fully loaded.

The trick is a combination of all the submissions on here

First you must create the map example:

let googleMap = new google.maps.Map(document.getElementById(targetMapId), 
{
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        streetViewControl: false,
        styles: [
          {
            featureType: "poi",
            elementType: "labels",
            stylers: [
              {visibility: "off"}
            ]
          }
        ],
      });

Then you need to set a default location for it to load.. it can be anywhere

googleMap.setCenter({
        lat: 26.12269,
        lng: -80.130172
      });

Then finally once it finishes loading the tiles for that location you can process code via the "tilesloaded" eent, this code can include re-centering the map, placing markers etc..

This ensures that the map is loaded before you do something with it

google.maps.event.addListenerOnce(googleMap, 'tilesloaded', function(){
// do something only the first time the map is loaded
});

Others have suggested the "idle" event as well, but I did not have much luck with that as it was hit or miss for me.

google.maps.event.addListenerOnce(googleMap, 'idle', function(){
// do something only the first time the map is loaded
});

Whereas when I used the "tilesloaded" , while I do get a quick blip then jump to the correct map view, it always works...so I went with the lesser of two evils

0

In my case, Tile Image loaded from remote url and tilesloaded event was triggered before render the image.

I solved with following dirty way.

var tileCount = 0;
var options = {
    getTileUrl: function(coord, zoom) {
        tileCount++;
        return "http://posnic.com/tiles/?param"+coord;
    },
    tileSize: new google.maps.Size(256, 256),
    opacity: 0.5,
    isPng: true
};
var MT = new google.maps.ImageMapType(options);
map.overlayMapTypes.setAt(0, MT);
google.maps.event.addListenerOnce(map, 'tilesloaded', function(){
    var checkExist = setInterval(function() {
        if ($('#map_canvas > div > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > div > div').length === tileCount) {
            callyourmethod();
            clearInterval(checkExist);
        }
    }, 100); // check every 100ms
});
Bala
  • 913
  • 9
  • 18
0

This days you know if the map is ready here:

void _onMapCreated(GoogleMapController controller) {
    this.controller = controller;
    _mapIsReady=true; //create this variable
  }

call this method from the map widget

return GoogleMap(
              myLocationEnabled: true,
              //markers: markers,
              markers: Set<Marker>.of(markers.values),
              onMapCreated: _onMapCreated,
              initialCameraPosition: CameraPosition(

                target: _initialPosition,
                zoom: 5.0,
              ),
            );
Thiago Silva
  • 670
  • 6
  • 18
0

I needed it for the calculating the map bounds, so this was enough for me:

new ResizeObserver(()=> updateMapBounds()).observe(map.getDiv())
new IntersectionObserver(()=> updateMapBounds()).observe(map.getDiv())
updateMapBounds();
ATP
  • 2,939
  • 4
  • 13
  • 34
0

We encountered a problem recently where neither idle nor tilesloaded events would trigger. The root cause was that the parent container had display: none; and the condition on our end to remove that attribute was for the map to be ready. This worked for us until February 23rd 2023 where it suddenly stopped working but starting on that date we were stuck in a situation where Google Maps was waiting for us to be ready and we were waiting for Google Maps to be ready.

Replacing display: none; with visibility: hidden; fixed it while also using the same listener as before:

google.maps.event.addListenerOnce(map, "idle", callback);
Pier-Luc Gendreau
  • 13,553
  • 4
  • 58
  • 69
-4

You could check the GMap2.isLoaded() method every n milliseconds to see if the map and all its tiles were loaded (window.setTimeout() or window.setInterval() are your friends).

While this won't give you the exact event of the load completion, it should be good enough to trigger your Javascript.

Alexander
  • 23,432
  • 11
  • 63
  • 73
fbuchinger
  • 4,494
  • 2
  • 30
  • 31