【问题标题】:Refreshing Google Maps API V3 Layers刷新 Google Maps API V3 层
【发布时间】:2014-09-05 14:08:46
【问题描述】:

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

根据我对文档的理解,我应该能够说“layer.setMap(null);”之类的话接着是“layer.setMap(map);”刷新图层(来源:https://developers.google.com/maps/documentation/javascript/reference#TrafficLayer)。

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

我尝试了几件事,包括:

有没有办法确保浏览器在不强制重新加载整个页面的情况下呈现新图像?

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

【问题讨论】:

  • 谢谢!我确实查看了那篇文章(实际上它是我在帖子中引用的文章之一)。不幸的是,这对我不起作用。
  • 您是否在浏览器上游的任何地方访问代理或缓存?

标签: javascript html google-maps


【解决方案1】:

好的,我发现,上面提到的是trafficLayer.setMap(null)trafficLayer.setMap(map) - 只是切换 有流量的磁贴到没有流量的磁贴。 map.setZoom(map.getZoom())(以及任何其他缩放变量)也不起作用,因为切片已经在缓存中,而且谷歌脚本甚至不会尝试从服务器下载新的。

另外,如果你只是打开谷歌地图并打开交通图层,它似乎并不令人耳目一新!太蹩脚了,谷歌!

所以我们必须找到一种不同的方法来解决它。

首先想到的是使用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);                                                   
        }               
    }
}   

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

一些cmets:

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

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

顺便说一句,我发现交通真的会在实时时间发生变化——图块可能每秒都不同。

编辑

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

【讨论】:

  • 您,先生,很有创意!很好的开箱即用的想法。
  • 这非常有效。抱歉,我处理这件事的速度很慢。最近被淹了。
  • 请注意,googleapis.com 可能会随着时间的推移而变化,现在与mts1.google.com 略有不同。因此,删除域名并单独保留/vt\?pb 应该可以解决问题。
  • 现在过滤的 url 是 "/map/vt?pb="
  • 知道如何在 Angular 2+ 中做到这一点吗??
【解决方案2】:

我经常使用流量层。我添加了一个按钮来切换图层,但发现隐藏它我不得不将图层本身设置为空。

显示图层的代码:

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

然后再去隐藏图层:

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

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

【讨论】:

  • 所以我确实尝试了与您建议的类似的完全拆除和重建,虽然它看起来像是在做某事(我可以看到地图闪烁)但实际流量没有更新(由在尚未缓存任何内容的其他浏览器中拉取页面)。
【解决方案3】:

您刷新图层的方式运行良好。

为了证明这一点,编辑了您的代码:

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

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

我还在第一次设置图层地图后在 initMap 函数中添加了间隔。

希望对您有所帮助。

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

【讨论】:

  • 感谢您抽出宝贵时间查看此内容。我可能需要再澄清一点。该图层渲染得很好,但实际的交通数据已经过时了。我可以让它运行一个小时或更长时间,但仍然看不到任何变化(这包括修改代码以匹配你所做的)。完全有可能是环境因素阻止了我让它发挥作用,但我让其他几个人看到了同样的结果。
  • 嗨@manderson,不用担心,伙计,我确实认为您可能遇到与我在新西兰遇到的类似问题,因为交通数据没有实时更新。我建议您监控几天的流量,截屏并在一周内进行比较,或者说看看数据是否发生了变化。否则,可能值得向 Google 记录支持票。
  • 我会检查一下,然后再发回来。感谢您在这方面的坚持。
  • 很抱歉花了这么长时间才回复这个问题。我确实让页面运行了很长时间而没有注意到任何变化。我确实无意中手动平移了视图,这迫使刷新图块,所以我尝试以编程方式稍微改变纬度和经度,但这也不起作用。当我有东西要分享时会再次更新。
  • 一个类似的想法对我有用。 trafficLayerOnMap() { if (this.isTrafficEnabled) { this.trafficLayer.setMap(null); this.isTrafficEnabled = false; } 其他 { this.trafficLayer = 新 google.maps.TrafficLayer(); this.trafficLayer.setMap(this.map); this.isTrafficEnabled = true; } }
【解决方案4】:

试试这个代码sn-p,可能对你有帮助

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>

【讨论】:

    【解决方案5】:

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

    在搜索和测试之后,我得到了它与这三行的配合:

            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 :/
    

    我重复一遍。我不知道这是否适用于流量层,但无论如何都要测试它。它让我醒了 2 天。

    【讨论】:

    • 我做得更好——我做了 setZoom(-1) 并在 setInterval 回调中做了 setZoom(+1)。屏幕闪烁,所有瓷砖都没有重新加载。
    【解决方案6】:

    谷歌documentation 说:

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

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

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

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

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

    所以用上面更新的方法,下面的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
    

    包含交通数据,例如:

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

    【讨论】:

    • 仅供参考,据我所知,交通数据实际上嵌入在瓷砖中,而不是绘制在顶部。签入 Chrome、网络、预览。此外,这并没有比已经提出的解决方案更好,即我相信 API 会忽略 setZoom()。
    • @RichardTheKiwi 你是对的。我已经删除了该声明。但setZoom() 绝对不容忽视。如果没有该行,ViewportInfoService.GetViewportInfo 文件(流量数据)将永远不会重新获取。只需检查开发工具中的网络选项卡。
    【解决方案7】:

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

    现在正确的测试是:

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

    【讨论】:

      【解决方案8】:

      这可能对你有用。

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-05
        • 1970-01-01
        • 2013-06-27
        • 2011-02-20
        • 1970-01-01
        • 2011-09-05
        • 2011-02-26
        • 1970-01-01
        相关资源
        最近更新 更多