Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refreshing Google Maps API V3 Layers

I've been having trouble getting Google Maps API v3 to update correctly. I've got a javascript timer running that should be refreshing the traffic layer periodically but I'm not seeing it happening.

As I understand the documentation, I should be able to say something like "layer.setMap(null);" followed by "layer.setMap(map);" to refresh the layer (source: https://developers.google.com/maps/documentation/javascript/reference#TrafficLayer).

I know the new map tiles are being downloaded (for example, I can see them in the Resources section of Chrome's dev tools), but the browser isn't rendering them. There is probably something fundamental I'm missing.

I've tried several things, to include:

  • Using meta tags to disable caching: Using <meta> tags to turn off caching in all browsers?
  • Using a manifest file: How to prevent Google Maps API v3 from caching tiles (to save storage space)?
  • Disabling Chrome's browser caching (while keeping the dev tools open): Disabling Chrome cache for website development
  • Firing another event to refresh the layers: Google Maps refresh traffic layer
  • Completely re-initializing the map every timer event.

Is there a way to ensure the browser will render the new images without forcing a full page reload?

Below is a simplified version of the page (based off of the answer from Google Maps refresh traffic layer).

<html>
    <head>
        <title>Map Testing</title>
        <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=weather"></script>
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>

        <script type="text/javascript">
            var map,
                trafficLayer,
                mapTimerHandle;

            $(function() {
                initMap();
                mapTimerHandle = setInterval(refreshMap, 15000);
            });

            function refreshMap() {
                trafficLayer.setMap(null);
                trafficLayer.setMap(map);
            }

            function initMap() {
                var mapDiv = document.getElementById('map');

                map = new google.maps.Map(mapDiv, {zoom: 15, center: new google.maps.LatLng(40.7127, -74.0059)});

                trafficLayer = new google.maps.TrafficLayer();

                trafficLayer.setMap(map);
            }
        </script>
    </head>
    <body style="margin:0px;">
        <div id="map" style="width:100%; height:100%;"></div>
    </body>
</html>
like image 834
manderson Avatar asked Sep 05 '14 14:09

manderson


People also ask

How do I layer a map in Google Maps?

You can add as many layers as you want to your custom map, allowing you to separate the different components of your new map from each other, by clicking the “Add layer” button. If you want to rename this layer, select the three-dot menu icon next to the layer and then click “Rename Layer” in the drop-down menu.

What does layers mean in Google Maps?

Layers are objects on the map that consist of one or more separate items, but are manipulated as a single unit. Layers generally reflect collections of objects that you add on top of the map to designate a common association.

What are some of the main differences between the Google map API version 2 and version 3?

Google Maps v3 is very slow when it comes to subclassing overlay classes. Most of the time when you have some custom overlays on your map it will start to LAG which means it is unusable in most cases. Version 2 is much, much, much FASTER for REAL PURPOSES.


2 Answers

Ok, what i've found, and what is mentioned above is that trafficLayer.setMap(null) and trafficLayer.setMap(map) - just switches tiles with drawn traffic to tiles without traffic. Also map.setZoom(map.getZoom()) (and any other variaties of zoom) doesn't work because tiles are already in cache and google scripts don't even try to download fresh ones from server.

Also, seems that if you just open google maps and turn on traffic layer it's not refreshing! Such a lame, google!

So we have to find a different way to solve it.

First thought is to use window.location.reload(true) wich will flush image cache - and we see it works. Not a good way to go though - reloading whole page taking too long. How about reloading images? Let's try!

function reloadTiles() {     var tiles = $("#map-canvas").find("img");     for (var i = 0; i < tiles.length; i++) {         var src = $(tiles[i]).attr("src");         if (/googleapis.com\/vt\?pb=/.test(src)) {                           var new_src = src.split("&ts")[0] + '&ts=' + (new Date()).getTime();             $(tiles[i]).attr("src", new_src);                                                            }                    } }    

And we call this function every N seconds: setInterval(reloadTiles, 5000)

some comments:

$("#map-canvas").find("img") - will grab all images from your map container (map-canvas in my case). Not all are tiles so we need to filter them out - i've noticed that tiles are loaded from domains like mts(digit).googleapis.com/vt?pb=(hella long param). Other map images are loaded from maps.gstatic.com.

So we get tile images, add bogus parameter and change their src. Profit!

Btw, i've found that traffic really changes in real time - tiles may be different each second.

Edit

Oh, sorry, here's working sample. And it's a snowy Moscow with a huge traffic :)

like image 172
Sergio Avatar answered Oct 26 '22 06:10

Sergio


I use the traffic layer quite a bit. I have added a button to toggle the layer but found to hide it I had to set the layer itself as null.

My code to show the layer:

if (MapManager.trafficLayer == null)
{
      MapManager.trafficLayer = new google.maps.TrafficLayer();
}
MapManager.trafficLayer.setMap(MapManager.map);

Then to go and hide the layer again:

MapManager.trafficLayer.setMap(null);
MapManager.trafficLayer = null;

In an ideal way what you suggested above would be better but for me this seems to work just fine.

like image 30
TResponse Avatar answered Oct 26 '22 06:10

TResponse