OpenLayers - przerysowywanie mapy po zmianie rozmiaru kontenera

25

W mojej aplikacji internetowej chcę umożliwić użytkownikom ustawienie rozmiaru kontenera mapy.

Wszystko działało dobrze, gdy pojemnik został nieco rozszerzony (najwyraźniej dzieje się tak, ponieważ płytki, które były tuż za granicą, były już załadowane). Jednak gdy kontener zostanie znacznie rozszerzony (w poniższym przykładzie, o szerokości od 300 do 1000 pikseli), pozostało puste miejsce.

Jak przerysować mapę i dostosować ją do nowego rozmiaru?

Wywołanie redraw()na wszystkich warstwach nie pomogło. Przybliżanie i oddalanie też się nie zmieniło.

Testowałem to z opisanymi wynikami w Operze, Chrome i Firefox. Co zaskakujące, w IE8 problem nie wystąpił, a mapa automatycznie się dostosowała.

Uproszczona strona do testowania:

<html>
  <head>
    <style>
      #mapbox { 
        width: 300px;
        height: 500px;
        border: 1px solid black;
      }
    </style>

    <script src="http://openlayers.org/api/OpenLayers.js"></script>
  </head>

  <body>
    <div id="mapbox"></div>
    <input type="button" id="test" value="resize">

    <script>    
      var map = new OpenLayers.Map('mapbox');
      map.addLayer(new OpenLayers.Layer.OSM());      

      map.setCenter(
        new OpenLayers.LonLat(1000000, 7000000), 5);

      document.getElementById('test').onclick = function() {
        document.getElementById('mapbox').style.width = '1000px';
      }
    </script>
  </body>
</html>
Chochlik
źródło

Odpowiedzi:

35

Musisz wywołać interfejs API, aby zaktualizować rozmiar mapy.

http://dev.openlayers.org/docs/files/OpenLayers/Map-js.html#OpenLayers.Map.updateSize

Oto jak to robimy

window.onresize = function()
{
  setTimeout( function() { map.updateSize();}, 200);
}

Widzicie, że zrobiliśmy niewielkie opóźnienie i szczerze mówiąc, nie pamiętam dokładnego powodu, ale musieliśmy trochę poczekać, zanim zadzwonimy do API, aby zmienić rozmiar.

Vadim
źródło
1
Uważam, że opóźnienie zależy od twojej aplikacji. ;) W każdym razie dziękuję, jeszcze raz coś przeoczyłem w dokumentacji.
Imp
1
Nie widzę też powodu opóźnienia, więc go pominąłem. Dzięki
zod
1
@Vadim Wielki anser, ale dla mnie nie działa. Mój kod jest podobny body onload=init()i initinicjuje mapę. Czy to z tego powodu? Czy byłoby to dobre rozwiązanie dla responsywnego projektowania? window.onload=window.onresize=function(){//resize here. Dzięki
slevin,
Zastanawiam się, czy setTimout był próbą wywołania go tylko co 200 ms. Niestety jest to trochę bardziej skomplikowane, trzeba mieć setInterval, który biegnie co 200 ms, a następnie mieć wartość logiczną var didResize, która jest ustawiona na true onresize()i ustaw aby falsepo map.updateSize()nazywa.
andrewb
1
SetTimeout najprawdopodobniej zapewnił załadowanie mapy i zrenderowanie reszty domeny. Obecnie używam tego samego hacka z powodu mojego niezrozumienia cyklu życia widoku Marionetki.
ca0v
8

Tak, użyj map.updateSize () jak mówi Vadim (też nie wiem, dlaczego opóźnienie!) Dokumentację

Zwykle umieszczam przycisk przełączania pełnoekranowego na mapach, co działa po prostu przełączając klasę css kontenera mapy, a następnie wywołując updateSize ()

function toggleFullScreen(mapContainer) {
    if ($(mapContainer).hasClass("normal")) {
        $(mapContainer).addClass("fullscreen").removeClass("normal");
    } else {
        $(mapContainer).addClass("normal").removeClass("fullscreen");
    }
    map.updateSize();
}
andyb
źródło
2

Nie jest elegancki, ale działał dobrze dla mnie

window.onresize = function(event)
{
   map.zoomOut(); map.zoomIn();
}
JFHack
źródło
to była jedyna odpowiedź, która zadziałała dla mnie
Matthew Lock
2

Kolejny komentarz do pierwszej (poprawnej) odpowiedzi:

Limit czasu-Zdarzenie jest potrzebny, jeśli czekasz na zdarzenie window.resize. W przeciwnym razie rozmiar mapy będzie zmieniany co milisekundę, jeśli użytkownik zacznie zmieniać rozmiar okna (potrzebowałem go w przeglądarce Firefox). Dlatego jeśli chcesz sprawdzić rozmiar okna, to limit czasu jest całkiem przydatny względnie. potrzebne. Zobacz: /programming/5489946/jquery-how-to-wait-for-the-end-or-resize-event-and-only-then-perform-an-ac lub jQuery zmiana rozmiaru zdarzenia końcowego

(przepraszam, nie mogę dodać komentarza, dlatego inna odpowiedź)

Leole
źródło
1

Próbowałem wszystkich opisanych tutaj rzeczy, ale nic nie działało dla mnie. Uświadomiłem sobie, że kiedy umieszczałem na mapie klasę „pełnoekranową”, zdarzenie zmiany rozmiaru nie zostało uruchomione. Naprawiam to za pomocą:

$(window).trigger('resize');
nicolasaiz173
źródło
1

Sposób użycia setTimeout powyżej nie ma dla mnie większego sensu (może to obejście dla starszej wersji OL), ale setTimeout może być użyty do zmniejszenia liczby wywołań map.updateSize () i innych powiązanych kodów, takich jak to:

$(window).resize(function () {
  if (window.resizeMapUpdateTimer) {
    clearTimeout(window.resizeMapUpdateTimer)
  }
  window.resizeMapUpdateTimer= setTimeout(function () {
    // Update container size
    map.updateSize()
  }, 200)
})
Simon Hutchison
źródło
0

myślę, że zmiana stylu div mapy automatycznie zmieni rozmiar panelu mapy.

document.getElementById("map-panel").style.width = "500px";

Mam nadzieję, że Ci to pomoże...

Aragonia
źródło
Po zmianie rozmiaru atrybuty rozmiaru kontenera działają dla mapy, ale nie dla rysowanych obiektów. Dodanie updateSize () zapewnia, że ​​funkcje są widoczne.
kode
0

To działa dla mnie:

this.$nextTick(
    function() {
        OL_MAP_INSTANCE.updateSize();
    }
);

$ NextTick jest ważny, ponieważ pozwoli poczekać na kolejne odświeżenie przed uwzględnieniem nowego rozmiaru kontenera mapy.

Lekarz
źródło