GIS and Media fusion

"The explosive growth of the GeoWeb and geographic information has made GIS powerful media for the general public to communicate, but perhaps more importantly, GIS have also become media for constructive dialogs and interactions about social issues." - Sui & Goodchild

User Tools

Site Tools


geoinf16:ol3tuto2

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
geoinf16:ol3tuto2 [2016/11/02 21:51]
oertz [Ex7A : découverte de la gestion événementielle cartographique]
geoinf16:ol3tuto2 [2017/11/29 22:06]
oertz [Ex7A : découverte de la gestion événementielle cartographique]
Line 1: Line 1:
 ====== Workshop OpenLayers (2016, part 2) ====== ====== Workshop OpenLayers (2016, part 2) ======
 ===== 7. Contrôles et interactions ===== ===== 7. Contrôles et interactions =====
-OpenLayers offre un ensemble de fonctionnalités permettant d'​interagir avec la carte. Par défaut, les interactions de zoom et pan sont actives mais il en existe d'​autres ([[http://​openlayers.org/​en/​v3.9.0/​apidoc/​ol.control.html?​unstable=true|ol.control]]). En plus de la gestion événementielle offerte par ces contrôleurs,​ OpenLayers permet d'​enregistrer des écouteurs sur de nombreux événements. Maintenant 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.+OpenLayers offre un ensemble de fonctionnalités permettant d'​interagir avec la carte. Par défaut, les interactions de zoom et pan sont actives mais il en existe d'​autres ([[http://​openlayers.org/​en/​v3.9.0/​apidoc/​ol.control.html?​unstable=true|ol.control]]). En plus de la gestion événementielle offerte par ces contrôleurs,​ OpenLayers permet d'​enregistrer des écouteurs sur de nombreux événements. Maintenant 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 la carte, ses couches et les objets géographiques représentés.
  
 ==== Ex7A : découverte de la gestion événementielle cartographique ==== ==== Ex7A : découverte de la gestion événementielle cartographique ====
-Cet exemple démontre qu'il est nécessaire qu'un gestionnaire s'​occupe spécifiquement d'​évenements cartographiques comme ceux en lien avec la vie d'un ol.Map (voir [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.MapBrowserEvent.html?​unstable=true#​event:​click|ol.MapBrowserEvents]]) ou ceux relatifs à la vie d'une [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.layer.Vector.html|ol.layer.Vector]].+Cet exemple démontre qu'il est nécessaire qu'un gestionnaire s'​occupe spécifiquement d'​évenements cartographiques comme ceux en lien avec la vie d'un ol.Map (voir [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.MapBrowserEvent.html?​unstable=true#​event:​click|ol.MapBrowserEvents]]) ou ceux relatifs à la vie d'une [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.layer.Vector.html|ol.layer.Vector]], d'une [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.source.Vector.html|ol.source.Vector]],​ etc.
  
 On reprend ici l'​exemple 5A : On reprend ici l'​exemple 5A :
Line 94: Line 94:
  
 ==== Ex7B : contrôle d'​interrogation en mode image (WMS GetFeatureInfo) ==== ==== Ex7B : contrôle d'​interrogation en mode image (WMS GetFeatureInfo) ====
-Le gestionnaire d'​événements cartographiques va notamment servir à déployer la dernière fonctionnalité de base d'une application de webmapping, celle qui consiste à interroger les objets de la carte.+Le gestionnaire d'​événements cartographiques va notamment servir à déployer la dernière fonctionnalité de base d'une application de webmapping, celle qui consiste à interroger les objets de la carte. ​
  
-Avant d'​aller plus loinajouter le serveur cartographique ci-dessous dans le fichier ​**config.js** ​(voir aussi https://​github.com/​camel113/​geoinf15-ol3/​blob/​tutoOL3.9.0/​js/​config.js) : +:!: Avant toutveillez à mettre à jour votre **config.js** ​à partir de la dernière version de l'​archive {{:geoinf16:geoinf16-ol3.zip|}} ​(celle-ci ajoute le serveur ​http://geoteach.heig-vd.ch:8080/geoserver/geoinfo/wms)
-<​code>​ +
-/* +
- * With the UNEP GRID GeoServer you can play with layers +
- ​* ​(see the Global Risk Data Platform map at http://preview.grid.unep.ch/​index.php?​preview=map):​  +
- * - World +
- * - NationalParks +
- * - Cities_esri +
- * - etc (see http://preview.grid.unep.ch/​geoserver/wms?​REQUEST=GetCapabilities) +
- */ +
-var unWMS = "​http://​preview.grid.unep.ch/​geoserver/​wms";​ +
-var unWFS = "​http://​preview.grid.unep.ch/​geoserver/​wfs";​ +
-</​code>​+
  
-Cet exemple illustre l'​interrogation des objets de la carte par le simple clic d'un pixel sur la carte. On enregistre un écouteur sur la map à l'aide de la méthode [[http://​openlayers.org/​en/​v3.9.0/​apidoc/​ol.Map.html?​unstable=true#​on|ol.Map.on]] afin d'​exécuter du code lors d'un click sur la map. On utilise ensuite la méthode [[http://​openlayers.org/​en/​v3.9.0/​apidoc/​ol.source.ImageWMS.html?​unstable=true#​getGetFeatureInfoUrl|ol.source.ImageWMS.getGetFeatureInfoUrl]] pour construire l'URL qui permet d'​interroger le WMS. Enfin, la fonction //​getFeatureInfo(url)//​ permet d'​envoyer une requête au serveur WMS à l'aide de l'URL précédemment construite. C'est l'​équivalent bien mieux structuré que http://​www.mediamaps.ch/​oltuto/​Ex0c_navmap.html.+Cet exemple illustre l'​interrogation des objets de la carte par le simple clic d'un pixel sur la carte. On enregistre un écouteur sur la map à l'aide de la méthode [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.Map.html?​unstable=true#​on|ol.Map.on]] afin d'​exécuter du code lors d'un click sur la map. On utilise ensuite la méthode [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.source.ImageWMS.html?​unstable=true#​getGetFeatureInfoUrl|ol.source.ImageWMS.getGetFeatureInfoUrl]] pour construire l'URL qui permet d'​interroger le WMS. Enfin, la fonction //​getFeatureInfo(url)//​ permet d'​envoyer une requête au serveur WMS à l'aide de l'URL précédemment construite. C'est l'​équivalent bien mieux structuré que http://​www.mediamaps.ch/​oltuto/​Ex0c_navmap.html.
  
 <​code>​ <​code>​
Line 118: Line 106:
         <script type="​text/​javascript"​ src="​js/​config.js"></​script>​         <script type="​text/​javascript"​ src="​js/​config.js"></​script>​
         <script type="​text/​javascript">​         <script type="​text/​javascript">​
-            var map, vectors, wmsLayer;+            var map, wmsLayer; 
             $(document).ready(function () {             $(document).ready(function () {
- 
-                var wmsSource = new ol.source.ImageWMS({ 
-                    url: unWMS, 
-                    params: { 
-                        VERSION: "​1.1.1",​ 
-                        LAYERS: '​World',​ 
-                        FORMAT: '​image/​png',​ 
-                        STYLES: '​polygon'​ 
-                    } 
-                }); 
- 
-                wmsLayer = new ol.layer.Image({ 
-                    source: wmsSource 
-                }); 
- 
                 map = new ol.Map({                 map = new ol.Map({
                     target: '​map',​                     target: '​map',​
Line 142: Line 116:
                     })                     })
                 });                 });
-                 + 
-                // Create/Add a WMS baselayer +                ​var wmsLayer = new ol.layer.Tile({ 
-                wmsLayer = new ol.layer.Image({ +                    source: ​new ol.source.TileWMS({ 
-                    source: ​wmsSource+                        url: myOWS, 
 +                        params: { 
 +                            VERSION: "​1.0.0",​ 
 +                            LAYERS: "​worldadm",​ 
 +                            FORMAT: "​image/​png"​ 
 +                        } 
 +                    })
                 });                 });
-                map.addLayer(wmsLayer); ​            ​+                map.addLayer(wmsLayer);​
  
                 map.on('​singleclick',​ function (evt) {                 map.on('​singleclick',​ function (evt) {
 +                    var wmsSource = wmsLayer.getSource();​
                     var url = wmsSource.getGetFeatureInfoUrl(                     var url = wmsSource.getGetFeatureInfoUrl(
                             evt.coordinate,​                             evt.coordinate,​
Line 155: Line 136:
                             "​EPSG:​3857",​                             "​EPSG:​3857",​
                             {                             {
-                                INFO_FORMAT:​ "text/plain"+                                INFO_FORMAT:​ "text/html"
                             }                             }
                     );                     );
-                    if (url) +                    if (url) getFeatureInfo(url);​
-                        ​getFeatureInfo(url);​+
                 });                 });
  
Line 165: Line 145:
                     var url2 = encodeURIComponent(url);​                     var url2 = encodeURIComponent(url);​
                     var request = $.ajax({                     var request = $.ajax({
-                        url: "​php/​proxy2.php?​url="​ + url2, +                        url: "​php/​proxy2.php?​url="​ + url2,      // oui, on a besoin d'un proxy ! 
-                        dataType: "​text"​,+                        dataType: "​text"​
                     });                     });
  
Line 188: Line 168:
                 position: absolute;                 position: absolute;
                 top: 20px;                 top: 20px;
-                left: 50px;+                left: 60px;
                 background-color:​ white;                 background-color:​ white;
                 border: solid gray 1px;                 border: solid gray 1px;
Line 205: Line 185:
  
 __TODO__ __TODO__
-  - Modifier paramètre INFO_FORMAT et ajouter le paramètre FEATURE_COUNT comme suit :<​code>​ 
-{ 
-    INFO_FORMAT:​ "​text/​html",​ 
-    FEATURE_COUNT:​ 50 
-}</​code>​ et cliquer la carte aux alentours du Liechtenstein (sans changer de zoom !). 
   - Modifier encore une fois INFO_FORMAT comme suit :<​code>​   - Modifier encore une fois INFO_FORMAT comme suit :<​code>​
 INFO_FORMAT:​ "​application/​json",​ INFO_FORMAT:​ "​application/​json",​
-</​code>​ que se passe-t-il à l'​interrogation de la carte ? Regarder le flux client/​serveur ... +</​code>​ que se passe-t-il à l'​interrogation de la carte ? Regarder le flux client/​serveur ... et exploitez-le pour n'​afficher que le nom de pays
-  - Remplacer ​la toute la **fonction getFeatureInfo** par celle-ci :<​code>​+  - Remplacer la **fonction getFeatureInfo** par celle-ci :<​code>​
 function getFeatureInfo(url) { function getFeatureInfo(url) {
     var url2 = encodeURIComponent(url);​     var url2 = encodeURIComponent(url);​
     var request = $.ajax({     var request = $.ajax({
         url: "​php/​proxy2.php?​url="​ + url2,         url: "​php/​proxy2.php?​url="​ + url2,
-        dataType: "json",+        dataType: "text"
     });     });
  
Line 230: Line 205:
  
         if (features.length > 0) {         if (features.length > 0) {
-            sldUrl = "​http://​www.mediamaps.ch/​oltuto/​php/​GetWorldSLD.php?​ID="​ + features[0].get("​terr_id"); +            sldUrl = "​http://​www.mediamaps.ch/​oltuto/​php/​GetWorldSLD.php?​ID="​ + features[0].get("​GMI_CNTRY"); 
-            console.log(sldUrl);​+            ​//console.log(sldUrl);​
             wmsLayer.getSource().updateParams({             wmsLayer.getSource().updateParams({
                 VERSION: "​1.1.1",​                 VERSION: "​1.1.1",​
Line 237: Line 212:
                 SLD: sldUrl                 SLD: sldUrl
             });             });
-            $("#​info"​).html(features[0].get("​terr_name"));+            $("#​info"​).html(features[0].get("​NAME"));
         }         }
     });     });
Line 246: Line 221:
 } }
 </​code>​ </​code>​
 +  - Encore une autre solution pour faire un "​highlight"​ de l'​entité,​ en deux étapes : 
 +    * ajouter une couche vecteur : <​code>​
 +vectors = new ol.layer.Vector({
 +    source: new ol.source.Vector()
 +});
 +map.addLayer(vectors);​
 +</​code>​
 +    * remplaçer le callback //​request.done//​ comme suit<​code>​
 +request.done(function (data) {
 +    decoder = new ol.format.GeoJSON();​
 +    features = decoder.readFeatures(data,​ {
 +        dataProjection:​ "​EPSG:​4326",​
 +        featureProjection:​ "​EPSG:​3857"​
 +    });
 +    //​console.log(features);​
  
-==== Ex7C : WMS GetFeature avec chargement vector d'​entité(s) et interaction ​==== +    if (features.length > 0) { 
-La réponse de la requète GetFeature étant un flux GeoJSON completle navigateur reçoit la géométrie de l'​entité ​"sous le clique cartographique". On peut l'exploiter et interagir comme suit :+        vectors.getSource().clear();​ 
 +        vectors.getSource().addFeatures(features);​ 
 +        $("#​info"​).html(features[0].get("​NAME"​));​ 
 +    } 
 +}); 
 +</​code>​ 
 + 
 + 
 +==== Ex7C : Interaction sur entités vectors ​==== 
 +Après les utilisations possibles pour interagir avec les entités représentées par les services cartographiquesvoyons comme interagir directement avec les entités vectors ​"vivantes" ​client-side. On tulise pour cela le concept d'[[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.interaction.html?​unstable=true|ol.interaction]],​ notamment [[http://​openlayers.org/​en/​v3.19.1/​apidoc/​ol.interaction.Select.html?​unstable=true|ol.interaction.Select]].
  
 <​code>​ <​code>​
 <​html>​ <​html>​
     <​head>​     <​head>​
-        <​title>​ol3 - Ex7C - interaction with WMS GetFeatureInfo + vector loading</​title>​+        <​title>​ol3 - Ex7C - Interaction sur entités vectors</​title>​
         <script type="​text/​javascript"​ src="​js/​config.js"></​script>​         <script type="​text/​javascript"​ src="​js/​config.js"></​script>​
         <script type="​text/​javascript">​         <script type="​text/​javascript">​
-            var map, vectors, wmsLayer;+            var map;
             $(document).ready(function () {             $(document).ready(function () {
- 
-                var wmsSource = new ol.source.ImageWMS({ 
-                    url: unWMS, 
-                    params: { 
-                        VERSION: "​1.1.1",​ 
-                        LAYERS: '​World',​ 
-                        FORMAT: '​image/​png',​ 
-                        STYLES: '​polygon'​ 
-                    } 
-                }); 
- 
                 map = new ol.Map({                 map = new ol.Map({
 +                    view: new ol.View({
 +                        center: [738600, 5840171],
 +                        zoom: 3
 +                    }),
                     target: '​map',​                     target: '​map',​
-                    ​view: new ol.View({ +                    ​layers
-                        ​center: ol.proj.transform([6.7, 46.7], 'EPSG:4326', 'EPSG:3857')+                        ​new ol.layer.Tile({ 
-                        ​zoom4+                            ​sourcenew ol.source.OSM(
 +                        }) 
 +                    ] 
 +                }); 
 +                vectorLayer = new ol.layer.Vector({ 
 +                    sourcenew ol.source.Vector({ 
 +                        url"​http://​earthquake.usgs.gov/​earthquakes/​feed/​v1.0/​summary/​2.5_day.geojson"​
 +                        ​formatnew ol.format.GeoJSON()
                     })                     })
                 });                 });
-                 +                ​map.addLayer(vectorLayer);​ 
-                // Create/Add a WMS baselayer + 
-                ​wmsLayer ​= new ol.layer.Image({ +                ​var selectInteraction ​= new ol.interaction.Select({ 
-                    ​sourcewmsSource+                    ​conditionol.events.condition.singleClick,​ 
 +                    layers: [vectorLayer] ​  // the layers on which the selection is possible
                 });                 });
-                map.addLayer(wmsLayer);+                map.addInteraction(selectInteraction);
  
-                // Create/add an empty vector layer +                ​selectInteraction.on('​select',​ function (e) { 
-                ​vectors ​new ol.layer.Vector(+                    if (e.target.getFeatures().getLength() > 0) { 
-                    source: new ol.source.Vector()+                        ​//console.log(e.target.getFeatures().item(0).getKeys());​ 
 +                        var title e.target.getFeatures().item(0).get("​title"​)
 +                        $("#​info"​).html(title);​ 
 +                    }
                 });                 });
-                map.addLayer(vectors);​ 
-                ​ 
-                map.on('​singleclick',​ function (evt) { 
-                    var url = wmsSource.getGetFeatureInfoUrl( 
-                            evt.coordinate,​ 
-                            map.getView().getResolution(),​ 
-                            "​EPSG:​3857",​ 
-                            { 
-                                INFO_FORMAT:​ "​application/​json",​ 
-                                FEATURE_COUNT:​ 1 
-                            } 
-                    ); 
-                    if (url) 
-                        getFeatureInfo(url);​ 
-                }); 
- 
-                function getFeatureInfo(url) { 
-                    var url2 = encodeURIComponent(url);​ 
-                    var request = $.ajax({ 
-                        url: "​php/​proxy2.php?​url="​ + url2, 
-                        dataType: "​json",​ 
-                    }); 
- 
-                    request.done(function (data) { 
-                        decoder = new ol.format.GeoJSON();​ 
-                        features = decoder.readFeatures(data,​ { 
-                            dataProjection:​ "​EPSG:​4326",​ 
-                            featureProjection:​ "​EPSG:​3857"​ 
-                        }); 
- 
-                        if (features.length > 0) { 
-                            vectors.getSource().clear();​ 
-                            vectors.getSource().addFeatures(features);​ 
-                            $("#​info"​).html(features[0].get("​terr_name"​));​ 
-                        } 
-                    }); 
- 
-                    request.fail(function (jqXHR, textStatus) { 
-                        alert("​Request failed: " + textStatus);​ 
-                    }); 
-                } 
             });             });
         </​script>​         </​script>​
Line 339: Line 301:
                 position: absolute;                 position: absolute;
                 top: 20px;                 top: 20px;
-                left: 50px;+                left: 60px;
                 background-color:​ white;                 background-color:​ white;
                 border: solid gray 1px;                 border: solid gray 1px;
Line 350: Line 312:
     <​body>​     <​body>​
         <div id="​map"></​div>​         <div id="​map"></​div>​
-        <div id="​info">​Click on the map to get feature info</​div>​+        <div id="​info">​Select ​on the map to get feature info</​div>​
     </​body>​     </​body>​
 </​html>​ </​html>​
Line 356: Line 318:
  
 __TODO__ __TODO__
-  - Adapter l'​exemple pour afficher dans l'​infobox aussi la capitale du pays en question (ex. Liechtenstein [capital: Vaduz]). +  - Utiliser ​l'​[[http://​openlayers.org/​en/​v3.19.1/apidoc/ol.events.condition.html|ol.events.condition]] qui va bien pour avoir le comportement type "on mouse over"​. ​Sans oublier de mettre l'IHM en cohérence.  
-  - Modifier aussi l'​affichage de l'​infobox selon goût. +  - Configurer l'​interaction ​de sorte que l'​utilisateur puisse aussi cliquer sur la bulle d'​information pour aller à la page des détails du séisme (cf propriété //url//, exhttp://earthquake.usgs.gov/earthquakes/eventpage/​nc72722700){{:​geoinf16:​selectearthquake.png?nolink|}}
-  - Modifier FEATURE_COUNT à 50 et cliquer aux alentours du Liechtenstein. Quelle critique peut-on formuler sur cet état de l'​exemple ? +
-  - Ajouter ​l'​[[http://​openlayers.org/​en/​v3.9.0/apidoc/ol.interaction.html|ol.interaction]] suivante :<​code>​ +
-var selectPointerMove = new ol.interaction.Select({ +
-    condition: ​ol.events.condition.pointerMove,​ +
-    layers: [vectors  // in our case this is optional as we only one vector layer in the map +
-}); +
- +
-map.addInteraction(selectPointerMove);​ +
- +
-selectPointerMove.on('​select',​ function (e) { +
-    if (e.target.getFeatures().getLength() > 0) { +
-        $("#​info"​).html(e.target.getFeatures().item(0).get('terr_name'​));​ +
-    } else { +
-        $("#​info"​).empty();​ +
-    } +
-}); +
-</​code>​ +
-  - Mettre ​en commentaire la ligne :<​code>​ +
-vectors.getSource().clear();​ +
-</​code>​ +
-  - Modifier le style de sélection en exploitant ​la propriété **style** de la classe [[http://openlayers.org/en/v3.9.0/apidoc/ol.interaction.Select.html|ol.interaction.Select]].+
  
 ==== Ex7D : stratégies de chargement vector ==== ==== Ex7D : stratégies de chargement vector ====
-Le chargement en mode vector d'​entités géographiques ouvre des possibilités intéressantes en termme ​d'​interaction utilisateur au point d'​être tenté de toujours tout charger dans le navigateur. Une telle approche peut s'​avérer piégeuse et 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. Des stratégies de chargement peuvent alors s'​avérer utiles afin d'​éviter des écueils.+Le chargement en mode vector d'​entités géographiques ouvre des possibilités intéressantes en terme d'​interaction utilisateur au point d'​être tenté de toujours tout charger dans le navigateur. Une telle approche peut s'​avérer piégeuse et 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. Des stratégies de chargement peuvent alors s'​avérer utiles afin d'​éviter des écueils.
  
 Avant d'​aller plus loin, charger le **script proxy1.php** dans le dossier php du projet : https://​github.com/​camel113/​geoinf15-ol3/​blob/​tutoOL3.9.0/​php/​proxy1.php. Avant d'​aller plus loin, charger le **script proxy1.php** dans le dossier php du projet : https://​github.com/​camel113/​geoinf15-ol3/​blob/​tutoOL3.9.0/​php/​proxy1.php.
geoinf16/ol3tuto2.txt · Last modified: 2018/05/16 10:05 (external edit)