OpenLayers - redessiner la carte après le redimensionnement du conteneur

25

Dans mon application Web, je souhaite permettre aux utilisateurs de définir la taille du conteneur de carte.

Tout a bien fonctionné lorsque le conteneur a été légèrement agrandi (apparemment, c'est parce que les tuiles qui étaient juste derrière la frontière étaient déjà chargées). Cependant, lorsque le conteneur est considérablement développé (dans l'exemple suivant, de 300 à 1 000 pixels de largeur), il reste de l'espace vide.

Comment redessiner la carte et l'adapter à la nouvelle taille?

Appeler redraw()sur toutes les couches n'a pas aidé. Ni zoom avant ni arrière.

J'ai testé cela avec les résultats décrits dans Opera, Chrome et Firefox. Dans IE8, étonnamment, le problème ne s'est pas produit et la carte s'est automatiquement adaptée.

Une page Web simplifiée pour les tests:

<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>
Lutin
la source

Réponses:

35

Vous devez appeler l'API pour mettre à jour la taille de la carte.

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

Voici comment nous procédons

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

Vous pouvez voir que nous avons fait un léger retard, et honnêtement, je ne me souviens pas de la raison exacte, mais nous avons dû lui donner une légère attente avant d'appeler l'API pour se redimensionner.

Vadim
la source
1
Eh bien, je pense que le délai dépend de votre application. ;) Quoi qu'il en soit, merci, encore une fois j'ai raté quelque chose dans la documentation.
Imp
1
Je ne vois pas non plus de raison du retard, alors laissez-le de côté. Merci
zod
1
@Vadim Great anser, mais ne fonctionne pas pour moi. Mon code est comme body onload=init()et initinitialise la carte. Est-ce à cause de cela? En outre, serait-ce une bonne solution pour une conception réactive? window.onload=window.onresize=function(){//resize here. Merci
slevin
Je me demande si setTimout était une tentative de le faire appeler uniquement toutes les 200 ms. Malheureusement, c'est un peu plus compliqué, il faut avoir un setIntervalqui s'exécute toutes les 200 ms, puis avoir un booléen var didResizequi est défini sur true onresize(), et défini sur falseaprès map.updateSize()est appelé.
andrewb
1
Le setTimeout était susceptible de garantir que la carte était chargée et que le reste du dom était rendu. J'utilise actuellement le même hack en raison de mon manque de compréhension du cycle de vie de la vue Marionette.
ca0v
8

Oui, utilisez map.updateSize () comme le dit Vadim (également pas sûr pourquoi le retard!) Documentation

Je mets généralement un bouton bascule plein écran sur les cartes, ce qui fonctionne simplement en changeant la classe css du conteneur de carte, puis en appelant updateSize ()

function toggleFullScreen(mapContainer) {
    if ($(mapContainer).hasClass("normal")) {
        $(mapContainer).addClass("fullscreen").removeClass("normal");
    } else {
        $(mapContainer).addClass("normal").removeClass("fullscreen");
    }
    map.updateSize();
}
andyb
la source
2

N'est pas élégant, mais cela a bien fonctionné pour moi

window.onresize = function(event)
{
   map.zoomOut(); map.zoomIn();
}
JFHack
la source
ce fut la seule réponse qui a fonctionné pour moi
Matthew Lock
2

Un autre commentaire à la première (correcte) réponse:

L'événement timeout est nécessaire si vous attendez l'événement window.resize. Sinon, la carte sera redimensionnée toutes les millisecondes si un utilisateur commence à redimensionner la fenêtre (j'en avais besoin pour Firefox). Par conséquent, si vous souhaitez vérifier la taille de la fenêtre, le délai d'expiration est très utile resp. nécessaire. Voir: /programming/5489946/jquery-how-to-wait-for-the-end-or-resize-event-and-only-then-perform-an-ac ou jQuery resize end event end

(désolé, je ne peux pas ajouter de commentaire, donc une autre réponse)

leole
la source
1

J'ai essayé toutes les choses décrites ici mais rien n'a fonctionné pour moi. J'ai donc réalisé que lorsque je mettais une classe «plein écran» sur la carte, l'événement de redimensionnement n'était pas déclenché. Je corrige cela avec:

$(window).trigger('resize');
nicolasaiz173
la source
1

La façon dont setTimeout est utilisé ci-dessus n'a pas beaucoup de sens pour moi (peut-être une solution de contournement pour une ancienne version OL), mais setTimeout peut être utilisé pour réduire le nombre d'appels à map.updateSize (), et tout autre code associé comme cette:

$(window).resize(function () {
  if (window.resizeMapUpdateTimer) {
    clearTimeout(window.resizeMapUpdateTimer)
  }
  window.resizeMapUpdateTimer= setTimeout(function () {
    // Update container size
    map.updateSize()
  }, 200)
})
Simon Hutchison
la source
0

je pense que changer le style de div de carte automatiquement changera la taille du panneau de carte.

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

J'espère que ça t'aide...

Aragon
la source
Lors du redimensionnement, la modification des attributs de taille du conteneur fonctionne pour la carte, mais pas pour les entités dessinées. L'ajout de updateSize () garantit que les fonctionnalités sont visibles.
kode
0

Cela fonctionne pour moi:

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

Le $ nextTick est important car il permettra d'attendre la prochaine actualisation avant de prendre en compte la nouvelle taille du conteneur de carte.

Médecin
la source