Обновление слоев 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>
Ответы
Ответ 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)) {
...