Javascript 刷新 Google Maps API V3 图层

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25687831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:42:44  来源:igfitidea点击:

Refreshing Google Maps API V3 Layers

javascripthtmlgoogle-maps

提问by manderson

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

我一直无法正确更新 Google Maps API v3。我有一个 javascript 计时器正在运行,它应该定期刷新流量层,但我没有看到它发生。

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).

根据我对文档的理解,我应该能够说“layer.setMap(null);”之类的东西。后跟“layer.setMap(map);” 刷新图层(来源: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.

我知道正在下载新的地图图块(例如,我可以在 Chrome 开发工具的资源部分看到它们),但浏览器没有呈现它们。我可能缺少一些基本的东西。

I've tried several things, to include:

我尝试了几件事,包括:

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).

以下是页面的简化版本(基于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>

采纳答案by Sergio

Ok, what i've found, and what is mentioned above is that trafficLayer.setMap(null)and trafficLayer.setMap(map)- just switchestiles 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.

好吧,我已经找到了,并且上面提到的那是什么trafficLayer.setMap(null)trafficLayer.setMap(map)-只是开关与绘制交通瓷砖瓷砖没有交通。此外map.setZoom(map.getZoom())(以及任何其他缩放变体)也不起作用,因为图块已经在缓存中,谷歌脚本甚至不会尝试从服务器下载新的图块。

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!

第一个想法是使用它window.location.reload(true)会刷新图像缓存 - 我们看到它有效。虽然不是一个好方法 - 重新加载整个页面需要太长时间。重新加载图像怎么样?咱们试试吧!

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)

我们每 N 秒调用一次这个函数: setInterval(reloadTiles, 5000)

some comments:

一些评论:

$("#map-canvas").find("img")- will grab all images from your map container (map-canvasin 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.

$("#map-canvas").find("img")- 将从您的地图容器中获取所有图像(map-canvas在我的情况下)。并不是所有的都是瓷砖,所以我们需要过滤掉它们——我注意到瓷砖是从mts(digit).googleapis.com/vt?pb=(hella long param). 其他地图图像从 加载maps.gstatic.com

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

所以我们得到平铺图像,添加虚假参数并更改它们的 src。利润!

Btw, i've found that traffic reallychanges in realtime - tiles may be different each second.

顺便说一句,我发现流量确实实时变化的 - 瓷砖可能每秒都不同。

Edit

编辑

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

哦,对不起,这是工作样本。这是一个白雪皑皑的莫斯科,交通拥堵:)

回答by renambot

Sergio's answer is still the correct one but I believe Google updated their API and URLs (a risk mentioned by a commenter).

Sergio 的答案仍然是正确的,但我相信 Google 更新了他们的 API 和 URL(评论者提到的风险)。

The correct test would be now:

正确的测试现在是:

....
if (/googleapis.com\/maps\/vt\?pb=/.test(src)) {
...

回答by loan.burger

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.

以理想的方式,你上面建议的会更好,但对我来说这似乎工作得很好。

回答by loan.burger

The way you are refreshing the layer is working fine.

您刷新图层的方式工作正常。

Here is your code edited to prove this:

这是您编辑的代码以证明这一点:

<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;          
        var vis = false;

        $(function ()
        {
            initMap();            
        });

        function refreshMap()
        {               
            if (vis)            
            {
                trafficLayer.setMap(null)
                vis = false;
            }
            else
            {
                trafficLayer.setMap(map);
                vis = true;
            }            
        }

        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);
            vis = true;
            setInterval(function ()
            {
                refreshMap();
            }, 3000);
        }
    </script>
</head>
<body style="margin:0px;">
    <div id="map" style="width:100%; height:100%;"></div>
</body>

I added a visibility property to toggle the layer every 2 seconds. You will notice how it turns on and off. Because the way you called it I think it did not have enough time to refresh.

我添加了一个可见性属性来每 2 秒切换一次图层。您会注意到它是如何打开和关闭的。因为你叫它的方式我认为它没有足够的时间来刷新。

Also I added the interval in the initMap function after the layer's map was first set.

此外,我在首次设置图层地图后在 initMap 函数中添加了间隔。

Hope that helps.

希望有帮助。

EDIT. Just to add to this, where the traffic is real time where supported, in some cases its based on historic data and will not refresh over a short period. But the traffic data is fetched at the time of each request as specified in the docs: https://developers.google.com/maps/documentation/javascript/trafficlayer#traffic_layer

编辑。补充一点,在支持流量的情况下,流量是实时的,在某些情况下,它基于历史数据,不会在短时间内刷新。但是流量数据是在文档中指定的每个请求时获取的:https: //developers.google.com/maps/documentation/javascript/trafficlayer#traffic_layer

回答by Eko Junaidi Salam

try this code snippet, may be this help you out

试试这个代码片段,可能对你有帮助

function init() {
    var map,
    trafficLayer,
    mapTimerHandle;

    var mapDiv = document.getElementById('map');

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

    trafficLayer = new google.maps.TrafficLayer();
    trafficLayer.setMap(map);
}

$(document).ready(function () {
    init();
    setInterval(function () {
        google.maps.event.trigger(map, 'resize');
        map.fitBounds();
    }, 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>

<div id="map" style="width:600px; height:450px"></div>

回答by Onur Y?ld?r?m

Google documentationsays:

谷歌文档说:

The Google Maps API allows you to add real-timetraffic information (where supported) to your maps using the TrafficLayer object. Traffic information is provided for the time at which the request is made.

Google Maps API 允许您使用 TrafficLayer 对象向地图添加实时交通信息(如果支持)。提供请求时的交通信息。

I believe your refreshMap()function will only hide and show the traffic layer (via the .setMap()method) and will not actually fetch updated traffic data (if there is).

我相信您的refreshMap()函数只会隐藏和显示流量层(通过.setMap()方法),而不会实际获取更新的流量数据(如果有)。

So the only efficient way would be to renew your requestby re-initiating the TrafficLayer()object.

因此,唯一有效的方法是通过重新启动对象来更新您的请求TrafficLayer()

EDIT:I've monitored the network traffic and saw no new requests are made. The view has to be changed to force new data to be fetched (for example by re-setting the zoom)...

编辑:我监控了网络流量,没有看到任何新的请求。必须更改视图以强制获取新数据(例如通过重新设置缩放)...

function refreshMap() {
    trafficLayer.setMap(null);
    trafficLayer = null;
    map.setZoom(map.getZoom()); // this renews the view and forces new data to be requested
    setTimeout(function () {
        trafficLayer = new google.maps.TrafficLayer();
        trafficLayer.setMap(map);
    }, 100);
}

So with the updated method above, the JS file below is re-fetched from https://maps.googleapis.com/maps/api/js/:

所以使用上面更新的方法,下面的 JS 文件是从 重新获取的https://maps.googleapis.com/maps/api/js/

ViewportInfoService.GetViewportInfo?1m6&1m2&1d40.67711350268867&2d-74.09477919619036&2m2&1d40.747903965754034&2d-73.91666125686464&2u15&4sen-US&5e0&6sm%40285000000&7b0&8e0&9b0&callback=_xdc_._e0qzs3&token=110512

that contains traffic datasuch as:

包含交通数据,例如:

...,["traffic",[[40.74725696280421,-74.102783203125],[40.75557964275589,-73.916015625]]]...

回答by Esselans

I haven't work with traffic layers yet, so I'm not sure if this will work for you. I read the setZoom(getZoom()) trick but when I need to refresh the tiles (the classic one. The map itself) it didn't work either. I need to show/hide a grid in Gmaps (without reloading the page)

我还没有使用交通层,所以我不确定这是否适合你。我阅读了 setZoom(getZoom()) 技巧,但是当我需要刷新图块(经典图块。地图本身)时,它也不起作用。我需要在 Gmaps 中显示/隐藏网格(无需重新加载页面)

After searching and testing I got it working with these three lines:

经过搜索和测试,我得到了这三行代码:

        google.maps.event.trigger(map, 'resize'); // Can't remember if really helps
        map.setZoom( map.getZoom() -1 );    
        map.setZoom( map.getZoom() +1 ); // It won't flicker or make the transition between zoom levels. GMap just ignore the zoom change but redraw the tiles :/

I repeat. I don't know if this works with traffic layers but test it anyways. It kept me awake 2 days.

我重复。我不知道这是否适用于交通层,但无论如何都要进行测试。它让我保持清醒 2 天。

回答by Nagendra Badiganti

This might work for you. enter image description here

这可能对你有用。 在此处输入图片说明

    constructor(){
         this.mapOptions =  {
            zoom: 11,
            mapTypeId: google.maps.MapTypeId.HYBRID,
            mapTypeControl: false,
            streetViewControl: false,
            fullscreenControl: false
          }

         this.map = new google.maps.Map(
           this.mapElement.nativeElement,
           this.mapOptions
         );
         this.map.setCenter(this.latLng);
         this.map.setZoom(7);

         this.trafficLayer = new google.maps.TrafficLayer();
         // console.log(trafficLayer);
         this.trafficLayer.setMap(this.map);
        }

I Added traffic layer on the map initially, using the below code to toggle the traffic based on the user requirement

我最初在地图上添加了交通图层,使用以下代码根据用户要求切换交通

    // use this method to toggle traffic layer on the map. 
    trafficLayerOnMap() {
        if (this.isTrafficEnabled) {
          this.trafficLayer.setMap(null);
          this.isTrafficEnabled = false;
        } else {
          this.trafficLayer = new google.maps.TrafficLayer();
          this.trafficLayer.setMap(this.map);
          this.isTrafficEnabled = true;
        }
      }