====== Workshop OpenLayers v2 ... la suite ====== OpenLayers offre un ensemble de fonctionnalités permettant d'interagir avec la carte. Par défaut, les interactions de zoom et pan sont actives, et nous avons entre aperçu le contrôle OpenLayers.Control.LayerSwitcher. Il existe de nombreux autres [[http://dev.openlayers.org/docs/files/OpenLayers/Control-js.html|OpenLayers.Control]] (voir aussi http://docs.openlayers.org/library/controls.html et la section 8). En plus de la gestion événementielle offerte par ces contrôleurs, OpenLayers permet d'enregistrer des écouteurs sur de nombreux événements, comme ceux en lien avec la vie d'un OpenLayers.Map (voir [[http://dev.openlayers.org/releases/OpenLayers-2.13/doc/apidocs/files/OpenLayers/Map-js.html#OpenLayers.Map.events|OpenLayers.Map.events]], [[http://dev.openlayers.org/releases/OpenLayers-2.13/doc/apidocs/files/OpenLayers/Layer/Vector-js.html#OpenLayers.Layer.Vector.events|OpenLayers.Layer.Vector.events]]). Voir aussi un autre workshop sur le sujet : http://softlibre.gloobe.org/openlayers/workshop/introduction/module3. ===== 7. Feature access and controls ===== A présent que les techniques de visualisation cartographique sont maîtrisées, tant côté serveur que client, il s'agit de découvrir comment interagir avec les objets géographiques représentés. ==== Ex7A : contrôle d'interrogation en mode image (WMS GetFeatureInfo) ==== Cet exemple illustre l'interrogation des objets de la carte par le simple clic d'un pixel sur la carte. On utilise le contrôle [[http://dev.openlayers.org/releases/OpenLayers-2.13/doc/apidocs/files/OpenLayers/Control/WMSGetFeatureInfo-js.html|OpenLayers.Control.WMSGetFeatureInfo]] qui permet d'[[http://dev.openlayers.org/releases/OpenLayers-2.13/doc/apidocs/files/OpenLayers/Control-js.html#OpenLayers.Control.events|enregistrer un écouteur sur l'événement onGetFeatureInfo]]. Ex7A - interaction with WMS GetFeatureInfo control
Click on the map to get feature info
__TODO__ - Analyser l'échange client/serveur (ex. avec Firebug). Comment est-ce possible ? - Ajouter des paramètres dits "vendor" comme ci-dessous. Quel est l'effet ? info = new OpenLayers.Control.WMSGetFeatureInfo({ url: myWMS, infoFormat: 'text/plain', vendorParams: { radius: 5 } }); ==== Ex7B : un contrôle d'interrogation image "fait maison" ==== Dans Ex7A, c'est une version standardisé du contrôle d'interrogation lié au standard OGC WMS. L'exemple suivant montre comment mettre cela en oeuvre par nous-même. On s'assure ainsi de maîtriser tout le processus client/serveur. __Côté client :__ Ex7B - homemade GetFeatureInfo
Click on the map to get feature info
__Côté serveur :__ GetCountriesByXY.php rows; header("Content-type: application/json"); $i = 0; $fc = new FeatureCollection(); foreach ($rows as $row) { $fc->addFeature(new Feature($i++, json_decode($row->geom), array("name" => $row->name))); } echo json_encode($fc); ?> __TODO__ - Côté client, ajouter la ligne ci-dessous au bon endroit :$("#info").html("Loading... please wait..."); - Ajouter en fin de fonction //ready// une couche OpenLayers.Layer.Vector comme suit :vectors = new OpenLayers.Layer.Vector("FeatureInfo overlay"); map.addLayer(vectors); et remplacer l'appel AJAX comme suit : $.ajax({ type: "GET", url: getInfo, dataType: "text", success: function(response){ json = new OpenLayers.Format.GeoJSON(); fc = json.read(response); $("#info").html(fc[0].attributes.name); vectors.addFeatures(fc); } }); - Ajouter en fin de fonction //ready// le contrôle suivant avec son écouteur : selectControl = new OpenLayers.Control.SelectFeature(vectors, {hover:true}); map.addControl(selectControl); selectControl.activate(); vectors.events.register("featureselected", vectors, function(e){ $("#info").html(e.feature.attributes["name"]); }); - Enregistrer un écouteur sur le bon événement pour vider la
//info// quand le curseur sort d'un //feature//. ==== Ex7C : stratégies de chargement en mode vector ==== Le chargement d'entités géographiques peut s'avérer néfaste en terme d'expérience utilisateur du fait d'une latence provoquée (1) par le volume important de données à charger pour une bande passante donnée et (2) par les performances et l'aptitude du moteur de rendu cartographique à digérer ces données. L'exemple suivant montre déjà des limites avec la stratégie OpenLayers.Strategy.Fixed() qui charge simplement tous les objets dans l'enveloppe de visualisation. Il s'agit alors d'opter pour des stratégies afin d'éviter ces écueils. Ex7C - Vector overlay loading strategies
__TODO__ - Compter les appels au serveur géographique et vérifier le(s) volume(s) des entités géographiques transférées. - Faire de même avec le chargement de la couche //world_simple// en modifiant le paramètre ci-dessous : featureType: "world_simple" - Modifier la stratégie comme suit : strategies: [new OpenLayers.Strategy.BBOX()],et tout en naviguant dans la carte, compter les appels au serveur géographique et revérifier le(s) volume(s) des entités géographiques transférées. - Rendre la couche vector invisible au chargement de l'application en insérant l'instruction comme indiqué ci-dessous : ... lyr.setVisibility(false); map.addLayer(lyr); ... de plus, ajouter les instructions ci-dessous en fin de fonction //ready// : ... map.myZoom = map.zoomTo; map.zoomTo = function(zoom, xy) { lyr.setVisibility(zoom >= 8 ? true : false); map.myZoom(zoom, xy); }; - Quelles autres stratégies peut-on imaginer pour assurer une bonne expérience utilisateur ? ==== Ex7D : contrôles en mode vector ==== Le chargement d'entités géographiques (plutôt que leur représentation graphique image) offre des possibilités d'interaction plus directe sur les objets vectoriels qui les représentent. Voyons quelques exemples. __TODO__ - Sur la base de Ex7C avec la couche //cities//, définir les symbolizers //defaultPoint// et //selectPoint// suivant : defaultPoint = new OpenLayers.Symbolizer.Point({ graphicName: 'circle', pointRadius: 6, fillColor: '#0000ff', fillOpacity: 0.8 }); selectPoint = defaultPoint.clone(); selectPoint.fillColor = '#ff0000'; puis les connecter en ajoutant un //styleMap// sur la couche Vector comme suit : ... styleMap: new OpenLayers.StyleMap({ "default": new OpenLayers.Style(defaultPoint), "select": new OpenLayers.Style(selectPoint) }) ... enfin ajouter et activer un contrôle //SelectFeature// sur cette couche Vector comme suit : selectControl = new OpenLayers.Control.SelectFeature(lyr, {hover:true}); map.addControl(selectControl); selectControl.activate(); - Ajouter encore les instructions suivantes pour interroger les objets : lyr.events.register("featureselected", lyr, function(event) { var feature = event.feature; $("#info").html(feature.attributes.wup_aggl); }); - Faire le nécessaire pour améliorer l'interaction utilisateur : - afficher aussi le nom du pays dans la boîte d'information; - la boîte doit être vide quand aucun objet n'est sélectionné. - Que peut-on faire avec : feature.geometry.getBounds().getCenterLonLat() et une OpenLayers.Popup http://dev.openlayers.org/docs/files/OpenLayers/Popup-js.html ? ===== Autres interactions et contrôles ===== * [[http://ogo.heig-vd.ch/wiki/doku.php?id=ogo14:oltuto#ex7edes_outils_de_dessin|Des outils de dessin]] * [[http://ogo.heig-vd.ch/wiki/doku.php?id=ogo14:oltuto#ex7bmise_en_place_d_un_openlayerscontrolpanel|Mise en place d'un OpenLayers.Control.Panel]] * [[http://ogo.heig-vd.ch/wiki/doku.php?id=ogo14:oltuto#ex7aun_premier_exemple_pour_piloter_ces_outils_d_interactions|Un autre exemple pour piloter ces outils d'interactions]]