Pytanie Odświeżanie warstw API V3 interfejsu API Map Google


Mam problemy z uaktualnieniem Google Maps API v3. Mam uruchomiony timer javascript powinien okresowo odświeżaj warstwę ruchu, ale nie widzę, żeby to się stało.

Jak rozumiem dokumentację, powinienem móc powiedzieć coś w stylu "layer.setMap (null);" następnie "layer.setMap (mapa);" odświeżyć warstwę (źródło: https://developers.google.com/maps/documentation/javascript/reference#TrafficLayer).

Wiem, że pobierane są nowe kafelki mapy (na przykład widzę je w sekcji Zasoby narzędzi do tworzenia Chrome), ale przeglądarka ich nie renderuje. Pewnie jest coś podstawowego, czego mi brakuje.

Próbowałem już kilku rzeczy, włączając:

Czy istnieje sposób, aby przeglądarka renderowała nowe obrazy bez wymuszania pełnego przeładowania strony?

Poniżej znajduje się uproszczona wersja strony (oparta na odpowiedzi od Google Maps odświeża warstwę ruchu).

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

21
2017-09-05 14:08


pochodzenie


Dzięki! Sprawdziłem ten artykuł (w rzeczywistości jest to jeden z artykułów, do których pisałem w moim poście). Niestety to nie działało dla mnie. - manderson
Czy trafiasz w proxy lub cache nigdzie wcześniej w przeglądarce? - James Westgate


Odpowiedzi:


Ok, co znalazłem, i to, co zostało wspomniane powyżej, jest takie trafficLayer.setMap(null)  i trafficLayer.setMap(map) - właśnie przełączniki płytki z ciągniętym ruchem do płytek bez ruchu. Również map.setZoom(map.getZoom()) (i wszelkie inne warianty powiększenia) nie działa, ponieważ płytki są już w pamięci podręcznej, a skrypty google nawet nie próbują pobierać nowych z serwera.

Wydaje się również, że jeśli otworzysz mapy google i włączysz warstwę ruchu, to nie odświeżysz się! Taki lame, google!

Musimy więc znaleźć inny sposób rozwiązania tego problemu.

Pierwsza myśl jest do użycia window.location.reload(true) który wypłukuje pamięć podręczną obrazu - i widzimy, że działa. To nie jest dobra droga - przeładowywanie całej strony trwa zbyt długo. Co powiesz na ponowne ładowanie obrazów? Spróbujmy!

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

I nazywamy tę funkcję co N sekund: setInterval(reloadTiles, 5000)

Niektóre komentarze:

$("#map-canvas").find("img") - pobierze wszystkie obrazy z twojego kontenera mapy (map-canvas w moim przypadku). Nie wszystkie są kaflami, więc musimy je odfiltrować - zauważyłem, że płytki są ładowane z domen takich jak mts(digit).googleapis.com/vt?pb=(hella long param). Inne obrazy mapy są załadowane z maps.gstatic.com.

Dostajemy więc obrazy płytek, dodajemy fałszywe parametry i zmieniamy ich src. Zysk!

Btw, znalazłem ten ruch naprawdę zmiany w real czas - płytki mogą się różnić w każdej sekundzie.

Edytować

Przepraszam, oto jest próbka robocza. A to śnieżna Moskwa z ogromnym ruchem :)


22
2018-01-12 15:02



Jesteś bardzo pomysłowy! Niezłe myślenie na luzie. - RichardTheKiwi
Dobry trik! bardzo dobrze zrobione. - Onur Yıldırım
To działało idealnie. Przepraszam, że jestem powolny, żeby się do tego zabrać. Niedawno został zalany. - manderson
Tylko uwaga, googleapis.com może się zmieniać z biegiem czasu i teraz jest trochę inaczej mts1.google.com. Dlatego usunięcie nazwy domeny i pozostawiając /vt\?pb sam powinien rozwiązać problem. - alalp
Teraz adres URL filtru to "/ map / vt? Pb =" - lg.


Używam trochę warstwy ruchu. Dodałem przycisk, aby przełączyć warstwę, ale ją ukryłem. Musiałem ustawić samą warstwę jako pustą.

Mój kod do wyświetlenia warstwy:

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

Następnie ponownie otwórz i ukryj warstwę:

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

W idealny sposób to, co sugerujesz powyżej, byłoby lepsze, ale wydaje mi się, że to działa dobrze.


1
2017-11-13 21:43



Tak więc spróbowałem kompletnego zerwania i odbudowania podobnego do tego, co zasugerowałeś, i chociaż działa tak, jakby coś robił (widzę migającą mapę), rzeczywisty ruch nie jest aktualizowany (zweryfikowany przez przeciągnięcie strony w innej przeglądarce, gdzie nic nie zostało jeszcze zbuforowane). - manderson


Sposób, w jaki odświeżasz warstwę, działa dobrze.

Oto Twój kod edytowany, aby to udowodnić:

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

Dodałem właściwość widoczności, aby przełączać warstwę co 2 sekundy. Zobaczysz, jak włącza się i wyłącza. Ponieważ tak to nazwałeś, wydaje mi się, że nie było czasu na odświeżenie.

Dodałem także interwał w funkcji initMap po wcześniejszym ustawieniu mapy warstwy.

Nadzieja, która pomaga.

EDYTOWAĆ. Wystarczy dodać, że tam, gdzie ruch jest obsługiwany w czasie rzeczywistym, w niektórych przypadkach jest on oparty na danych historycznych i nie będzie odświeżany w krótkim okresie. Ale dane o ruchu są pobierane w momencie każdego żądania, jak określono w dokumentacji: https://developers.google.com/maps/documentation/javascript/trafficlayer#traffic_layer


1
2017-11-16 22:28



Doceniam twoje poświęcenie czasu na to. Być może będę musiał wyjaśnić nieco więcej. Warstwa jest w porządku, ale rzeczywiste dane o ruchu są nieaktualne. Mogę pozwolić mu działać przez godzinę lub dłużej i nadal nie widzę żadnych zmian (dotyczy to również modyfikacji kodu, aby dopasować to, co zrobiłeś). Jest całkowicie możliwe, że jest coś, co uniemożliwia mi zabranie tego do pracy, ale widziałem kilka osób, które mają takie same wyniki. - manderson
Hi @manderson, nie martw się kolega, myślę, że możesz mieć podobny problem jak w NZ, ponieważ dane o ruchu nie są aktualizowane w czasie rzeczywistym. Zalecam monitorowanie ruchu przez kilka dni, robienie zrzutu ekranu i porównywanie go w ciągu tygodnia lub mówienie i sprawdzanie, czy dane się zmieniły. w przeciwnym razie warto zarejestrować zgłoszenie do pomocy technicznej w Google. - loan.burger
Sprawdzę to i opublikuję później. Dzięki za trzymanie się mnie w tej sprawie. - manderson
Przepraszam, że tak długo wracam do tego. Pozwoliłem stronie działać przez dłuższy czas, nie zauważając żadnych zmian. Nieumyślnie obróciłem widok ręcznie, co wymusiło odświeżenie kafelków, więc próbowałem programowo zmienić szerokość i długość geograficzną, ale to też nie zadziałało. Zaktualizuje się ponownie, gdy będę miał coś do przekazania. - manderson


spróbuj tego fragmentu kodu, może to ci pomóc

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>


1
2018-01-09 17:31





Nie pracuję jeszcze z warstwami ruchu, więc nie jestem pewien, czy to zadziała. Czytałem trik setZoom (getZoom ()), ale gdy potrzebuję odświeżać kafelki (klasyczną, sama mapa) to też nie działa. Muszę pokazać / ukryć siatkę w Gmaps (bez ponownego ładowania strony)

Po wyszukaniu i przetestowaniu udało mi się go obsłużyć tymi trzema liniami:

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

Powtarzam. Nie wiem, czy to działa z warstwami ruchu, ale mimo to je przetestuj. Nie zasypiałem 2 dni.


1
2018-01-11 22:22



Poszedłem o jeden lepszy - zrobiłem setZoom (-1) i wywołanie zwrotne setInterval, setZoom (+1). Ekran zamigotał i wszystko, i NIE WOLNO przeładowywać płytek. - RichardTheKiwi


Google dokumentacja mówi:

Interfejs API Map Google umożliwia dodawanie czas rzeczywisty informacje o ruchu (jeśli są obsługiwane) do map za pomocą obiektu TrafficLayer. Informacje o ruchu są zapewnione czas, w którym złożono wniosek.

Wierzę w twoje refreshMap() funkcja ukryje i wyświetli warstwę ruchu (przez .setMap() metoda) i faktycznie nie pobierze zaktualizowanych danych o ruchu (jeśli jest).

Tak więc jedynym skutecznym sposobem byłoby odnowienie twojego żądanie przez ponowne zainicjowanie TrafficLayer() obiekt.

EDYTOWAĆ: Monitorowałem ruch w sieci i nie widziałem żadnych nowych żądań. Widok należy zmienić, aby wymusić pobieranie nowych danych (na przykład przez ponowne ustawienie powiększenia) ...

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

W związku z powyższą zaktualizowaną metodą, plik JS poniżej zostanie ponownie pobrany 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

który zawiera dane o ruchu Jak na przykład:

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

1
2018-01-11 01:26



FYI, o ile widzę, dane o ruchu są rzeczywiście osadzone w kafelkach, a nie rysowane na wierzchu. Sprawdź w Chrome, sieci, podglądu. Ponadto nie działało to lepiej niż już proponowane rozwiązania, tj. SetZoom (<ten sam zoom>) jest ignorowany przez API. - RichardTheKiwi
@RichardTheKiwi Masz rację. Usunąłem to roszczenie. Ale setZoom() zdecydowanie nie jest ignorowane. Bez tej linii, ViewportInfoService.GetViewportInfo plik (dane traffinc) nigdy nie jest ponownie pobierany. Po prostu sprawdź kartę Sieć w Dev Tools. - Onur Yıldırım


Odpowiedź Sergio jest nadal poprawna, ale uważam, że Google zaktualizował swoje API i adresy URL (ryzyko wspomniane przez komentującego).

Prawidłowy test będzie teraz:

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

1
2017-12-02 00:01