Skip to content

OpenLayers

Le code ci-après illustre la création d'une carte interactive à l'aide de la librairie OpenLayers et d'extensions OL-ext développées par Viglino : LayerSwitcher control, et Popup overlay.

Les éléments de contrôle permettent de changer le fond de carte parmi les différents jeux de données accessible en WMTS et d'afficher/cacher les sites nucléaires en WFS (au format GeoJSON) via le service KANO.

Code

html
<!DOCTYPE html>
<html>
<head>
    <title>ASNR Planet - OpenLayers client demonstration</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Page icon -->
	<link rel="shortcut icon" type="image/x-icon" href="../irsn-planet-icon-64x64.png" />
    <!-- Add dependencies : OpenLayers version 6.13.0 css and js -->
    <link rel="stylesheet" href="../openlayers/ol@6.13.0/ol.css" />
    <script src="../openlayers/ol@6.13.0/ol.js"></script>
    <!-- Using viglino OpenLayers extensions :
        for LayerSwitcher, see : https://viglino.github.io/ol-ext/examples/control/map.switcher.html
        for Popup overlay, see : http://viglino.github.io/ol-ext/examples/popup/map.popup.html
    -->
    <link rel="stylesheet" href="../openlayers/viglino/ol-ext.css" />
    <link rel="stylesheet" href="../openlayers/viglino/map.switcher2.css" />
    <script type="text/javascript" src="../openlayers/viglino/ol-ext.js"></script>
    <style>
        body {
            margin:0;
            font-family: 'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;
        }
        .map {
            width: 100%;
            height: 100vh;
        }
        .select {
            cursor: pointer;
        }
        .ol-popup {
            max-width:300px;
            min-width:100px;
            min-height:1em;
        }
    </style>
</head>
<body>
    <div id="map" class="map"></div>
    <script type="text/javascript">
        // 
        // Here is the subdomain and token defintion
        // Note that it can be convenient to store these variables according a flavor (dev, test, prod)
        //
        var subdomain='planet.staging.ul2i.fr'
		var apiKey='jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5NTYwNDYxMC0wMjUzLTQ1NzEtYjYxOC05N2YwYmVmZmY0MjMiLCJuYW1lIjoiZG9jIiwiYXVkIjoicGxhbmV0LnN0YWdpbmcudWwyaS5mciIsImlzcyI6ImthbGlzaW8iLCJpYXQiOjE3NTA2NjY5MDV9.5NkFwnubsVu3L9LVEacorpCt8F7tr7lenPFNrWI6rjU'
        //
        // Here are the basemaps definition
        //
        var osm_bright = new ol.layer.Tile({
            title: 'OSM Bright',
            baseLayer: true, // set 'true' to manage exclusive visibility on layers (only one base layer is shown at a time)
            displayInLayerSwitcher: true, // set to 'false' to not display in the LayerSwitcher
            source: new ol.source.XYZ({
                attributions: '© <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/osm-bright/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: true // Visibility by default
        });
        var osm_terrain_bright = new ol.layer.Tile({
            title: 'OSM Terrain Bright',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/osm-terrain-bright/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var osm_dark = new ol.layer.Tile({
            title: 'OSM Dark',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/osm-dark/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_ortho = new ol.layer.Tile({
            title: 'Photographie Aériennes (IGN Ortho)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-ortho/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.jpeg?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_accentue = new ol.layer.Tile({
            title: 'IGN Plan (accentué)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-accentue/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_attenue = new ol.layer.Tile({
            title: 'IGN Plan (atténué)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-attenue/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_classique = new ol.layer.Tile({
            title: 'IGN Plan (classique)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-classique/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_epure = new ol.layer.Tile({
            title: 'IGN Plan (épuré)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-epure/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_gris = new ol.layer.Tile({
            title: 'IGN Plan (gris)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-gris/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_standard = new ol.layer.Tile({
            title: 'IGN Plan (standard)',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-standard/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ign_plan_adm = new ol.layer.Tile({
            title: 'IGN Plan & limites administratives Admin-Express',
            baseLayer: true,
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-plan-adm/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        // Creating base layer group
        var baseLayerGroup = new ol.layer.Group({
            title: 'Fonds de carte',
            openInLayerSwitcher: false, // Set to 'true' to have this group open by default in the LayerSwitcher
            layers: [
                osm_bright,
                osm_terrain_bright,
                osm_dark,
                ign_ortho,
                ign_plan_accentue,
                ign_plan_attenue,
                ign_plan_classique,
                ign_plan_epure,
                ign_plan_gris,
                ign_plan_standard,
                ign_plan_adm
            ]
        });
        //
        // Here are the administrative layers
        //
        var ignLimitsDark = new ol.layer.Tile({
            title: 'IGN Limits Dark',
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-limites-sombre/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var ignLimitsBright = new ol.layer.Tile({
            title: 'IGN Limits Bright',
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-limites-clair/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: true
        });
        var ignLimitsToponyms = new ol.layer.Tile({
            title: 'Limites administratives IGN (toponymes)',
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/ign-limites-toponymes/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: true
        });
        var gadmLimitsDark = new ol.layer.Tile({
            title: 'Limites GADM (sombre)',
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/gadm-dark/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var gadmLimitsBright = new ol.layer.Tile({
            title: 'Limites GADM (clair)',
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/gadm-bright/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        var gadmLimitsToponyms = new ol.layer.Tile({
            title: 'Limites administratives GADM (Toponymes)',
            source: new ol.source.XYZ({
                attributions: '© <a href="https:/ign.fr">IGN</a> contributors',
                url: 'https://api.' + subdomain + '/wmts/1.0.0/gadm-toponyms/default/GLOBAL_WEBMERCATOR/{z}/{y}/{x}.png?' + apiKey
            }),
            maxZoom: 18,
            visible: false
        });
        //
        // Creating adminsitrative layer group
        //
        var admLayerGroup = new ol.layer.Group({
            title: 'Limites administratives',
            openInLayerSwitcher: true, // Set to 'true' to have this group open by default in the LayerSwitcher
            layers: [
                ignLimitsDark,
                ignLimitsBright,
                ignLimitsToponyms,
                gadmLimitsDark,
                gadmLimitsBright,
                gadmLimitsToponyms,
            ]
        });
        //
        // Here is the nuclear sites overlay layer definition
        //
        var sites = new ol.layer.Vector({
            title: 'Sites',
            source: new ol.source.Vector({
                attributions: '', // Write here the name of the owner of the data
                format: new ol.format.GeoJSON(),
                url: 'https://api.' + subdomain + '/wfs?service=WFS&version=2.0.0&request=GetFeature&typeNames=site_centroid&outputformat=geojson&' + apiKey
            }),
            // Styling points
            style: new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill ({
                        color: 'red'
                    }),
                    stroke: new ol.style.Stroke({
                        color: 'black',
                        width: 1
                    })
                })
            }),
            maxZoom: 18,
            visible: true // Visibility by default
        });
        //
        // Here are the influence zones
        //
        var zi = new ol.layer.Vector({
            title: 'Zones d\'influence',
            source: new ol.source.Vector({
                attributions: '', // Write here the name of the owner of the data
                format: new ol.format.GeoJSON(),
                url: 'https://api.' + subdomain + '/wfs?service=WFS&version=2.0.0&request=GetFeature&typeNames=zi&outputformat=geojson&' + apiKey
            }),
            // Styling polygons
            style: new ol.style.Style({
                fill: new ol.style.Fill({
                    color: 'blue'
                }),
                stroke: new ol.style.Stroke({
                    color: 'red',
                    width: 1,
                })
            }),
            maxZoom: 18,
            visible: true, // Visibility by default
            opacity: 0.5 // Opacity by default
        });
        //
        // Creating nuclear data layer group
        //
        var dataLayerGroup = new ol.layer.Group({
            title: 'Données',
            openInLayerSwitcher: true, // Set to 'true' to have this group open by default in the LayerSwitcher
            layers: [
                zi,
                sites
            ]
        });
        /**
         * Elements that make up the popup.
         */
        var container = document.getElementById('popup');
        var content = document.getElementById('popup-content');
        var closer = document.getElementById('popup-closer');
        //
        // Adding overlay
        //
        var overlay = new ol.Overlay({
            element: container,
            autoPan: true,
            offset: [0, -10]
        });
        //
        // Popup overlay
        //
        var popup = new ol.Overlay.Popup ({
            popupClass: "default", // Select between predefined CSS : "tooltips", "warning" "black" "default", "tips", "shadow",
            closeBox: true, // Shows the popup close button
            onshow: function(){ console.log("You opened the box"); },
            onclose: function(){ console.log("You close the box"); },
            positioning: 'auto',
            autoPan: true,
            autoPanAnimation: { duration: 250 }
        });
        //
        // Loading layer groups in the map
        //
        var map = new ol.Map({
            target: 'map',
            layers: [
                baseLayerGroup,
                admLayerGroup,
                dataLayerGroup
            ],
            view: new ol.View({
                center: ol.proj.fromLonLat([3, 47]),
                zoom: 6
            }),
            overlays: [popup]
        });
        var layerSwitcher = new ol.control.LayerSwitcher();
        map.addControl(layerSwitcher);
        //
        // Control Select 
        //
        var select = new ol.interaction.Select({});
        map.addInteraction(select);
        //
        // On selected => show/hide popup
        //
        select.getFeatures().on(['add'], function(e) {
            var feature = e.element;
            var content = "";
            content += feature.get("name");
            popup.show(feature.getGeometry().getFirstCoordinate(), content); 
        });
        select.getFeatures().on(['remove'], function(e) {
            popup.hide(); 
        })
    </script>
</body>
</html>

Résultat