Подтвердить что ты не робот

Обновление слоев API Google Maps V3

У меня возникли проблемы с правильной обновлением API Карт Google. У меня запущен таймер javascript, который должен периодически обновлять поток трафика, но я не вижу, как это происходит.

Как я понимаю документацию, я могу сказать что-то вроде "layer.setMap(null)"; затем "layer.setMap(карта)"; для обновления слоя (источник: https://developers.google.com/maps/documentation/javascript/reference#TrafficLayer).

Я знаю, что загружаются новые фрагменты карты (например, я могу их увидеть в разделе "Ресурсы" инструментов Chrome dev), но браузер не выполняет их. Возможно, что-то фундаментальное, что мне не хватает.

Я пробовал несколько вещей, чтобы включить:

Есть ли способ гарантировать, что браузер будет визуализировать новые изображения без принудительной перезагрузки страницы?

Ниже приведен упрощенный вариант страницы (на основе ответа от Google Maps обновить уровень трафика).

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

Ответ 1

Хорошо, что я нашел, и что упомянуто выше, это то, что trafficLayer.setMap(null) и trafficLayer.setMap(map) - просто переключает плитки с нарисованным трафиком на плитки без трафика. Кроме того, map.setZoom(map.getZoom()) (и любые другие варианты масштабирования) не работает, потому что плитки уже находятся в кеше, а скрипты google даже не пытаются загружать свежие файлы с сервера.

Кроме того, кажется, что если вы просто открываете карты Google и включаете уровень трафика, это не освежает! Такой хромой, google!

Итак, нам нужно найти другой способ его решения.

Сначала нужно использовать 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)

несколько комментариев:

$("#map-canvas").find("img") - захватит все изображения из вашего контейнера карты (map-canvas в моем случае). Не все плитки, поэтому нам нужно их отфильтровать - я заметил, что плитки загружаются из таких доменов, как mts(digit).googleapis.com/vt?pb=(hella long param). Другие изображения карт загружаются из maps.gstatic.com.

Таким образом, мы получаем изображения с черепицей, добавляем фиктивный параметр и изменяем их src. Profit!

Btw, я обнаружил, что трафик действительно меняется в реальном времени - плитки могут быть разными каждую секунду.

Edit

О, извините, здесь рабочий образец. И это снежная Москва с огромным трафиком:)

Ответ 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

Ответ 4

попробуйте этот фрагмент кода, возможно, это поможет вам

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

Google documentation говорит:

API Карт Google позволяет добавлять в режиме реального времени информацию о трафике (где поддерживается) на ваши карты с использованием объекта TrafficLayer. Информация о трафике предоставляется для времени, в которое выполняется запрос.

Я считаю, что ваша функция refreshMap() только скроет и покажет уровень трафика (с помощью метода .setMap()) и фактически не будет получать обновленные данные трафика (если есть).

Таким образом, единственным эффективным способом было бы возобновить ваш запрос, повторно инициировав объект TrafficLayer().

EDIT: Я отслеживал сетевой трафик и не видел никаких новых запросов. Представление должно быть изменено для принудительного ввода новых данных (например, путем повторной установки увеличения)...

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

Ответ 6

Я еще не работал с уровнями трафика, поэтому я не уверен, что это сработает для вас. Я прочитал трюк 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 дня.

Ответ 7

Ответ Серджио по-прежнему остается верным, но я считаю, что Google обновил свой API и URL-адреса (риск, упомянутый комментатором).

Теперь правильный тест:

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