Vous avez un site web, vous avez des données SIG et vous souhaitez combiner les deux ? Je vais vous montrer comment facilement mettre en place une petite carte avec Open Layer.
Introduction
Lorsqu’il s’agit de mettre une carte dans un site internet, plusieurs possibilités s’offrent à vous :
- Google Maps et cie : simple et efficace mais peu personnalisable.
- Leaflet : simple et léger, très personnalisable.
- Open Layer : simple, très personnalisable et ultra puissant.
Alors je ne rentrerai pas dans le débat Open Layer vs Leaflet, certains sites vous renseigneront bien mieux que moi sur les différences entre les deux. J’ai pour ma part testé les deux et je préfère Open Layer de part sa conception modulaire qui me semble plus pratique et surtout bien plus extensible que Leaflet. Après, ça reste une question de choix personnels.
Maintenant que vous avez choisit Open Layer, attaquons la documentation. Là, c’est le drame. En effet, malgré les nombreux exemples et la documentation de l’API qui est très complète, Open Layer est compliqué à prendre en main pour quelqu’un qui débute. Je vous présente donc ici les clés pour démarrer simplement et rapidement avec Open Layer.
Principes
La base
Le principe est simple, pour afficher une carte avec Open Layer, il faut les éléments suivants :
- Une page HTML (bien évidemment) possédant un conteneur (div) qui sera utilisé pour afficher la carte.
- Un appel à la librairie Open Layer (pour en utiliser les fonctionnalités).
- Un fichier de configuration (pour personnaliser la carte).
- Un fichier CSS de mise en forme de la carte.
La librairie Open Layer tout comme le fichier CSS sont disponibles directement depuis le site d’Open Layer.
Nous utiliserons en plus la librairie Layer Switcher. Il s’agit d’une extension pour Open Layer qui permet de construire une légende automatiquement.
Un outil modulaire
Une carte créée avec Open Layer est composée d’objets. Les propriétés ou options de chacun de ces objets peuvent avoir différentes valeurs :
- Une valeur textuelle ou numérique.
'valeur'
ou1234
- Une liste de valeurs textuelles ou numériques (array :
[]
).['valeur 1', 'valeur 2']
ou[1,2,3,4]
- Un objet Open Layer.
- Une liste d’objets Open Layer (array :
[]
).
Ainsi, un objet peut contenir d’autres objets qui peuvent eux même contenir encore d’autres objets.
Ces objets emboités peuvent donc :
- Soit être définis au sein de leur parent
- Soit être définis dans une variable puis cette variable est utilisée dans le parent.
Voici un exemple d’une même définition mais présentée de deux façons différentes :
- En une seule fois
- Avec l’utilisation de variables appelées dans les parents.
new ol.Map({ // Option avec une valeur textuelle option_1: 'valeur', // Option avec plusieurs valeur numériques option_2: [0, 2, 3], // Option faisant appel à un autre objet Open Layer option_3: new ol.View({ // Option avec plusieurs valeurs textuelles option_A: [ 'valeur', 'valeur 2' ] }), // Option faisant appel à plusieurs autres objets Open Layer option_4: [ new ol.layer.Tile({ // Option avec une valeur textuelle option_A: 'valeur', // Option faisant appel à un autre objet Open Layer option_B: new ol.source.OSM() }), new ol.layer.Vector({ // Option faisant appel à plusieurs autres objets Open Layer option_Z: new ol.source.Vector({ // Option avec une valeur textuelle option_X: 'valeur', }) }) ] });
var variable_view = new ol.View({ // Option avec plusieurs valeurs textuelles option_A: [ 'valeur', 'valeur 2' ] }) var variable_layer_tile = new ol.layer.Tile({ // Option avec une valeur textuelle option_A: 'valeur', // Option faisant appel à un autre objet Open Layer option_B: new ol.source.OSM() }) var variable_source_vector = new ol.source.Vector({ // Option avec une valeur textuelle option_X: 'valeur', }) var variable_layer_vector = new ol.layer.Vector({ // Option faisant appel à plusieurs autres objets Open Layer // On utilise ici la variable définie plus tôt option_Z: variable_source_vector }) new ol.Map({ // Option avec une valeur textuelle option_1: 'valeur', // Option avec plusieurs valeur numériques option_2: [0, 2, 3], // Option faisant appel à un autre objet Open Layer // On utilise ici la variable définie plus tôt option_3: variable_view, // Option faisant appel à plusieurs autres objets Open Layer // On utilise ici les variables définies plus tôt option_4: [ variable_layer_tile, variable_layer_vector ] });
Vous verrez plus bas que j’utilise principalement la deuxième solution qui consiste à définir des variables puis à les utiliser. Ça permet d’avoir un code plus facilement maintenable et plus clair de mon point de vue.
Pour pouvoir utiliser une variable, il faut au préalable la déclarer. Ainsi, la lecture des fichiers de configurations que je vous propose peut être faite à l’envers, en partant de la carte pour remonter jusqu’aux différents éléments qui la compose.
Carte des objets
Pour s’y retrouver, voici une cartographie rapide et non exhaustive des principaux objets d’Open Layer. Vous pourrez y retrouver les principales propriétés ayant pour valeur d’autres objets.
Attention, certains objets sont des « classes de base » : il s’agit d’un objet générique dont est dérivée plusieurs objets spécifiques. J’ai utilisé cette classe de base comme valeur de propriété lorsque cette dernière peut utiliser n’importe quel objet dérivé de cette classe de base.
Dans le cas des classes de base, les propriétés des classes dérivée sont parfois listées pour limiter le nombre de paragraphe et simplifier la lecture.
ol.Map
Détails
Conteneur de carte
Utilisé par :
Propriétés :
layers:
ol.layer.Base
– Couches de données cartographiquesview:
ol.View
– Vue (emprise, rotation…)controls:
ol.Control
– Fonctionnalités (zoom, plein écran…)interactions:
ol.Interaction
– Interactions (déplacement…)overlays:
ol.Overlay
– Objets superposés (comme des contrôles mais liés à une position géographique)
ol.Control
Détails
Classe de base
Fonctionnalités
Utilisé par :
Classes dérivées et propriétés :
ol.control.Attribution
– Mentions légalesol.control.FullScreen
– Mode plein écranol.control.MousePosition
– Position de la sourisol.control.OverviewMap
– Mini cartelayers:
ol.layer.Base
– Couches de données cartographiqueview:
ol.View
– Vue (emprise, rotation…)
ol.control.Rotate
– Rotation de la carteol.control.ScaleLine
– Echelleol.control.ZoomSlider
– Barre de zoomol.control.ZoomToExtent
– Emprise initialeol.control.Zoom
– Zoom avant/arrière
ol.layer.Base
Détails
Classe de base
Couche de données cartographiques
Utilisé par :
Classes dérivées et propriétés :
ol.layer.Image
– Couche de type imagesource:
ol.source.Image
– Source de type image
ol.layer.Tile
– Couche tuiléesource:
ol.source.Tile
– Source de type tuile
ol.layer.Vector
– Couche vecteur mise à jour à chaque imagesource:
ol.source.Vector
– Source de données vecteursstyle:
ol.style.Style
– Style de couche
ol.layer.VectorImage
– Couche vecteur mise à jour hors animationsource:
ol.source.Vector
– Source de données vecteursstyle:
ol.style.Style
– Style de couche
ol.layer.VectorTile
– Couche vecteur tuiléesource:
ol.source.VectorTile
– Source de données vecteurs tuiléesstyle:
ol.style.Style
– Style de couche
ol.layer.Graticule
– Quadrillageol.layer.Heatmap
– Carte de chaleur
ol.source.Source
Détails
Classe de base
Source de données
Classes dérivées et propriétés :
ol.source.Image
– Source de type image non tuiléeol.source.ImageArcGISRest
– Service ArcGIS Restol.source.ImageCanvas
–ol.source.ImageMapGuide
– Mapguide serverol.source.ImageStatic
– Simple image statiqueol.source.ImageWMS
– Serveur WMSol.source.Raster
– Raster créé à la volée à partir d’autres donnéessource:
ol.source.Source
|ol.layer.Base
– Source des données
ol.source.Tile
– Source de type image tuiléeol.source.BingMaps
– Image tuilée Bing Mapsol.source.IIIF
– Image tuilée IIF Image APIol.source.TileArcGISRest
– Image tuilée ArcGIS Restol.source.TileJSON
– Image tuilée JSONol.source.TileWMS
– Image tuilée de serveur WMSol.source.WMTS
– Image tuilée de serveur WMTSol.source.XYZ
– Image tuilée au format XYZol.source.Zoomify
– Image tuilée au format Zoomifyol.source.VectorTile
– Données vecteur tuiléesol.source.UTFGrid
– Données d’interaction UTFGridtileGrid:
ol.tilegrid.TileGrid
– Format de la grille de tuilage
ol.source.Vector
– Source de type vecteurformat:
ol.format.Feature
ol.source.Cluster
– Sources de données vecteur ponctuelles clusterisées
ol.format.Feature
Détails
Classe de base
Format de données
Utilisé par :
Classes dérivées et propriétés :
ol.format.JSONFeature
– Format JSONol.format.EsriJSON
ol.format.GeoJSON
ol.format.TopoJSON
ol.format.MVT
– Format MVT de MapBoxol.format.TextFeature
– Données au format texteol.format.IGC
ol.format.Polyline
– Format de données encodées par algorithme Polylineol.format.WKT
– Données en Well Known Text
ol.format.XMLFeature
– Données au format XMLol.format.GPX
ol.format.KML
defaultStyle:
ol.style.Style
ol.format.OSMXML
ol.format.WFS
ol.format.WMSGetFeatureInfo
ol.style.Style
Détails
Stylisation des couches de données vecteur
Utilisé par :
Propriétés :
geometry:
ol.geom.Geometry
|ol.style.Style
– Forme du symbole géométriquefill:
ol.style.Fill
– Remplissage du symboleimage:
ol.style.Image
– Symbole de type imagestroke:
ol.style.Stroke
– Contour du symboletext:
ol.style.Text
– Étiquette de l’objet
ol.geom.Geometry
Détails
Classe de base
Formes géométriques
Utilisé par :
Classes dérivées et propriétés :
ol.geom.GeometryCollection
– Collection de géométriesgeometries:
ol.geom.Geometry
– Géométries présentes dans la collection
ol.geom.Point
– Pointcoordinates:
ol.coordinate
ol.geom.MultiPoint
– Multipointcoordinates:
ol.coordinate
ol.geom.LinearRing
– Contour circulairecoordinates:
ol.coordinate
ol.geom.LineString
– Lignecoordinates:
ol.coordinate
ol.geom.MultiLineString
– Multilignecoordinates:
ol.coordinate
|ol.geom.LineString
ol.geom.MultiPolygon
Multipolygonecoordinates:
ol.coordinate
|ol.geom.Polygon
ol.geom.Polygon
– Polygonecoordinates:
ol.coordinate
ol.geom.Circle
– Forme circulairecenter:
ol.coordinate
– Centre de la forme
ol.style.Image
Détails
Classe de base
Symbole
Utilisé par :
Classes dérivées et propriétés :
ol.style.Icon
– Imageol.style.RegularShape
– Polygone régulierfill:
ol.style.Fill
– Remplissagestroke:
ol.style.Stroke
– Contour
ol.style.Circle
– Cerclefill:
ol.style.Fill
– Remplissagestroke:
ol.style.Stroke
– Contour
ol.style.Fill
Détails
Remplissage
Utilisé par :
Propriétés :
color:
ol.color
ol.style.Stroke
Détails
Contour vecteur
Utilisé par :
Propriétés :
color:
ol.color
ol.style.Text
Détails
Etiquette de l’objet
Utilisé par :
Propriétés :
fill:
ol.style.Fill
– Remplissagestroke:
ol.style.Stroke
– ContourbackgroundFill:
ol.style.Fill
– RemplissagebackgroundStroke:
ol.style.Stroke
– Contour
Initialisation de la carte
Pour notre projet, nous allons avoir besoin des fichiers suivants :
- map.html : page qui sera consultée et qui contiendra la carte.
- ol_style.css : fichier CSS qui contiendra les styles de la page map.html ainsi que les personnalisations de notre carte (nous n’utiliserons qu’une partie des styles par défaut).
- Un fichier de configuration qui sera ici diviser en 4 fichiers pour simplifier la compréhension :
- ol_data_raster.js : fichier de configuration des données raster.
- ol_data_vector.js : fichier de configuration des données vecteur.
- ol_control.js : fichier de configuration des contrôles de la carte (boutons de zoom, légende, échelle…).
- ol_map.js : fichier de configuration de notre carte.
Voici les fichiers que vous devriez avoir avec le code associé :
# # Cliquez sur le nom des fichiers pour en afficher le contenu. #
<!DOCTYPE html> <html lang="fr"> <head> <!-- Balise méta --> <meta charset="UTF-8" /> <title>Open layer - Demonstration</title> <link rel="icon" type="image/png" href="https://ressource.arthurbazin.com/documents/image/favicon_arthurbazin.png" /> <!-- Eléments utiles --> <!-- Font Awesome (pour des icônes cool) --> <script src="https://kit.fontawesome.com/votre_cle_api.js" crossorigin="anonymous"></script> <!-- Police sympa --> <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <!-- Open Layers --> <!-- Style Open Layers --> <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v6.3.1/css/ol.css" type="text/css"> <!-- Bibliothèque Open Layers --> <script type="text/javascript" src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v6.3.1/build/ol.js"></script> <!-- Extension Open Layers - layerswitcher : paramétrage --> <script src="https://unpkg.com/ol-layerswitcher@3.5.0"></script> <!-- Extension Open Layers - layerswitcher : style --> <link rel="stylesheet" href="https://unpkg.com/ol-layerswitcher@3.5.0/src/ol-layerswitcher.css" /> <!-- Styles perso --> <link rel="stylesheet" href="ol_style.css" type="text/css"> </head> <body> <h1>Ma carte</h1> <p>Voici un exemple de carte</p> <!-- Emplacement de la carte --> <div id="ol_localisation" class="map"></div> <p>Bravo !!</p> <!-- Appel JS en fin de page --> <!-- Paramétrages Open Layers --> <!-- Attention, l'ordre à une importance --> <script type="text/javascript" src="ol_data_raster.js"></script> <script type="text/javascript" src="ol_data_vector.js"></script> <script type="text/javascript" src="ol_control.js"></script> <script type="text/javascript" src="ol_map.js"></script> </body> </html>
/************************----************************/ /* Open Layers */ /* Paramétrage données raster */ /****************************************************/
/************************----************************/ /* Open Layers */ /* Paramétrage données vecteur */ /****************************************************/
/************************----************************/ /* Open Layers */ /* Paramétrage des contrôles */ /****************************************************/
/************************----************************/ /* Open Layers */ /* Paramétrage carte */ /****************************************************/
/************************----************************/ /* Styles Open Layer */ /****************************************************/ /* Définitions générales */ body { background-color: rgb(42, 45, 53); } /* Textes */ body, p { font-family: 'Quicksand', sans-serif; color:#fff; font-size: 15px; line-height: 20px; font-weight: 200; } p { margin-bottom: 8px; margin-top: 8px; } h1{ font-size: 25px; font-weight: 500; text-transform: uppercase; margin-top: 0px; margin-bottom: 2px; } /* Conteneur carte */ .map { height: 450px; width: 80%; margin-left: auto; margin-right: auto; border-radius: 4px; background-color: #AF00FF; background-image: linear-gradient(332deg, #009FFF 0%, #AF00FF 100%); font-family: Arial, Helvetica, sans-serif; color: #000; } /* Open Layer */ /*Vide*/
Vous devriez normalement obtenir le résultat suivant (voir en plus grand) :
Pour le moment cette page affiche un rectangle vide. Il s’agit de l’emplacement de votre carte. Il va donc falloir personnaliser le contenu pour afficher quelque chose. Pour cela, plusieurs étapes :
- Personnalisation du contenu
- Personnalisation du style
Personnalisation du contenu
Le but est donc ici de paramétrer votre carte grâce aux fichiers de configuration.
Pour cela, nous avons vu qu’Open Layer est un outil modulaire : la carte est un objet JavaScript, composé d’objets, eux-mêmes composés d’objets etc. Ainsi, vous allez vite voir que nous allons avoir besoin de définir tout un tas d’objets que nous allons utiliser les uns à la suite des autres.
Nous allons donc partir de la définition de la carte pour ensuite définir tous les objets qui la composent. Voici quelques éléments de compréhension :
- Attention, bien qu’il soit possible de tout définir d’un seul coup, je préfère définir chaque objet séparément dans des variables.
- N’hésitez pas à utilisez la documentation d’Open Layer.
- Certaines propriétés n’ont pas besoin d’être définies, je les ai conservées mais commentées (pour mémoire).
Ajouter des données
Voici les fichiers de configuration que vous pouvez utiliser :
# # Cliquez sur le nom des fichiers pour en afficher le contenu. #
/************************----************************/ /* Open Layers */ /* Paramétrage données raster */ /****************************************************/ // Ce fichier contient la définition des fonds de plan que nous souhaitons afficher sur la carte // Nous allons ajouter trois fonds de plan différents (2 pour la carte et 1 que nous utiliserons plus tard dans la mini carte). // Les objets que l'on retrouve dans cette configuration (avec par indentation ce qu'ils contiennent) : // ol.layer.Tile : Couche de donnée tuilées // ol.source.OSM() : Source de données en provenance du site Open Street Map // ol.source.Stamen : Source de données en provenance du site Stamen // ol.source.XYZ : Source de données tuilées "XYZ" // Définition du fond de plan Open Street Map ///////////////////////////////////////////// var data_raster_osm = new ol.layer.Tile({ // Source de la couche source: new ol.source.OSM(), // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition de la couche (défaut : 0) //zIndex: 0, // Extension LayerSwitcher : Titre de la couche title: 'OSM', // Extension LayerSwitcher : Fond de plan : seul une seule couche de type 'base' est affichée à la fois type: 'base', }) // Définition du fond de plan Positron ////////////////////////////////////// var data_raster_positron = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://cartodb-basemaps-{a-c}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', // Mentions légales attributions:['© Contributeur <a href="https://www.openstreetmap.org/copyright" target="_blanc">OpenStreetMap</a>','© <a href="https://carto.com/attribution" target="_blanc">CARTO</a>'], }), // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition de la couche (défaut : 0) //zIndex: 0, // Extension LayerSwitcher : Titre de la couche title: 'Positron', // Extension LayerSwitcher : Fond de plan : seul une seule couche de type 'base' est affichée à la fois type: 'base', }) // Définition du fond de plan Open Street Map pour la mini carte //////////////////////////////////////////////////////////////// var data_raster_osm_minimap = new ol.layer.Tile({ // Source de la couche source: new ol.source.OSM(), // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition de la couche (défaut : 0) //zIndex: 0, // Extension LayerSwitcher : Titre de la couche title: 'OSM', // Extension LayerSwitcher : Fond de plan : seul une seule couche de type 'base' est affichée à la fois type: 'base', })
/************************----************************/ /* Open Layers */ /* Paramétrage données vecteur */ /****************************************************/ // Ce fichier contient la définition des données vecteurs que nous souhaitons afficher sur la carte // Nous allons définir 1 couche de données contenant des points représentant des emplacement dans 3 communes de Haute-Savoie. // Les objets que l'on retrouve dans cette configuration (avec par indentation ce qu'ils contiennent) : // ol.layer.Vector : Couche de données vecteur // ol.source.Vector : Source de données vecteur // ol.format.GeoJSON() : Lecteur de données au format GeoJSON // ol.style.Style : Stylisation d'une couche // ol.style.Icon : Style du symbole // ol.style.Text : Style des étiquettes // ol.style.Stroke : Style du contour // Définition des données source (format GeoJSON) ///////////////////////////////////////////////// var ol_source_layer_exemple = new ol.source.Vector({ features: new ol.format.GeoJSON().readFeatures( { 'type': 'FeatureCollection', 'features': [ { 'type': 'Feature', 'properties': { 'name': 'Lucinges' }, 'geometry': { 'type': 'Point', 'coordinates': [ 6.318435, 46.190029 ] } }, { 'type': 'Feature', 'properties': { 'name': 'Saint-Gervais' }, 'geometry': { 'type': 'Point', 'coordinates': [ 6.711486, 45.892829 ] } }, { 'type': 'Feature', 'properties': { 'name': 'Annecy' }, 'geometry': { 'type': 'Point', 'coordinates': [ 6.131432, 45.899263 ] } } ] }, {featureProjection: 'EPSG:3857'}, ) }) // Définition du style des données ////////////////////////////////// var ol_style_layer_exemple = new ol.style.Style({ // Remplissage des objets de la couche //fill // Utilisation d'une image image: new ol.style.Icon({ // Image source à utiliser src:'https://ressource.arthurbazin.com/demo/open_layer/ressource/placeholder_black.svg', // Dimension de l'image en pixel (défaut : [50, 50]) //size:[50,50], // Point d'ancrage de l'image (défaut : [0.5, 0.5]) //anchor: [0.5, 46], // Unité d'ancrage en X (défaut : 'fraction') //anchorXUnits: 'fraction', // Unité d'ancrage en Y (défaut : 'fraction') //anchorYUnits: 'pixels', // Opacité de l'image (défaut : 1) //opacity: 1, // Echelle de l'image (défaut : 1) scale:0.5, // Rotation de l'icone avec la vue (défaut : false) rotateWithView: true, // Rotation de l'icone en radian dans le sens des aiguille d'une montre (défaut : 0) //rotation:0, }), // Contour des objets //stroke // Etiquette des objets text: new ol.style.Text({ // Texte à afficher text: 'Salut', // Police (défaut : '10px sans-serif') //font:'10px sans-serif', // Décalage du texte en X en pixel (défaut : 0) //offsetX:0, // Décalage du texte en Y en pixel (défaut : 0) offsetY:19, // Le texte peut-il dépasser de l'opbjet ? (défaut : false) //overflow:false, // Placement du texte (défaut : 'point') // Valeur : 'point' ou 'line' si la forme est de type ligne ou polygone //placement:'point', // Echelle //scale:1, // Rotation du texte avec la carte (défault : false) rotateWithView:true, // Rotation du texte en radian (défaut : 0) //rotation:0, // Alignement du texte (défaut : 'center' si placement: 'point') // Valeur : 'left', 'right', 'center', 'end' ou 'start' //textAlign:'center', // Alignement vertical du texte (défault : middle) // Valeur : 'bottom', 'top', 'middle', 'alphabetic', 'hanging' ou 'ideographic' //textBaseline: middle, // Remplissage du texte //fill:, // Contour du texte stroke: new ol.style.Stroke({ color:[255, 255, 255, 0.7], //lineCap:round, //lineJoin:round, //lineDash //lineDashOffset //miterLimit width:3, }), // Remplissage du fond //backgroundFill:, // Contour du fond //backgroundStroke:, // Espacement autour du texte en pixel (Défaut : [0, 0, 0, 0]) (Ordre : [haut, droite, milieu, gauche]) //padding:[5, 5, 5, 5], }), }) // Définition de la couche de données ///////////////////////////////////// var data_vecteur_layer_exemple = new ol.layer.Vector({ // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition de la couche (défaut : 0) //zIndex: 0, // Emprise de rendu maximum // Emprise en xmin, ymin, xmax, ymax en 3857 //extent: [], // Ordre de rendu de la couche (ordre de dessin des couches) //renderOrder: 1, // Zone en pixel autour de la carte jusqu'ou la couche sera dessinée après chaque déplacement (défaut : 100) //renderBuffer: 100, // Mode de rendu de la couche (défaut : 'vector') // 'vector' : Rendu vecteur : plus précis durant les animations mais plus lourd // 'image' : Rendu image : moins précis durant les animations mais plus léger, les point et les étiquettes tournent avec la vue //renderMode: 'vector',*** // Gestion des conflits entre les objets (défaut : false) // Lorsqu'activé, la priorité des objets est définit avec la propriété zIndex du style //declutter: false, // Extension LayerSwitcher : Titre de la couche title: 'Couche exemple', // Source de la données source: ol_source_layer_exemple, // Style de la couche style: ol_style_layer_exemple, })
/************************----************************/ /* Open Layers */ /* Paramétrage carte */ /****************************************************/ // Ce fichier contient la définition de la carte // Les objets que l'on retrouve dans cette configuration (avec par indentation ce qu'ils contiennent) : // ol.Map : Carte que l'on verra dans la page HTML // ol.layer.Group : Groupe de couche (optionnel, on aura pu utiliser les couches directement) // ol.layer.Vector : Couche de donnée vecteur (définit dans ol_data_vector.js) // ol.layer.Tile : Couche de donnée raster (définit dans ol_data_raster.js) // ol.View : Vue de la carte (paramètres qui régissent ce que l'on voit dans la carte) // Définition de groupes de couches /////////////////////////////////// // Ceci est optionnel mais nous l'utiliserons plus tard dans la légende var data_group = [ // Groupe de couche 1 new ol.layer.Group({ // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition du groupe (défaut : 0) //zIndex: 0, // Extension LayerSwitcher : Titre de la couche : Extension LayerSwitcher title: 'Fond de plan', // Extension LayerSwitcher : Dépliage du groupe (défaut : 'open') fold: 'open', // Extension LayerSwitcher : Combiner plusieurs couches en une seule : le groupe fait office de "couche" //combine: true, // Couches de données contenues dans le groupe layers:[ data_raster_osm, data_raster_positron ], }), // Groupe de couche 2 new ol.layer.Group({ // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition du groupe (défaut : 0) //zIndex: 0, // Extension LayerSwitcher : Titre de la couche : Extension LayerSwitcher title: 'Vecteurs', // Extension LayerSwitcher : Dépliage du groupe (défaut : 'open') fold: 'open', // Extension LayerSwitcher : Combiner plusieurs couches en une seule : le groupe fait office de "couche" //combine: true, // Couches de données contenues dans le groupe layers:[ data_vecteur_layer_exemple, ], }), ] // Paramétrage de la vue //////////////////////// var vue_carte = new ol.View({ // Projection de la carte (défaut : 'EPSG:3857') //projection:'EPSG:3857', // Centre de la carte // On récupère les coordonnées depuis des coordonnées longitude/lattitude center: ol.proj.fromLonLat([5.918861, 45.888972]), // Extension maximale permise pour le centre de la carte // Emprise en xmin, ymin, xmax, ymax en 3857 //extent: [], // Résolution à l'ouverture en unité de carte par pixel resolution: 432, // Résolutions possibles pour l'utilisateur (en ordre décroissant) en unité de carte par pixel resolutions: [110693, 55346, 27673, 13837, 6918, 3459, 1730, 865, 432, 216, 108, 54, 27, 14, 7, 3.3, 1.6, 0.8, 0.4, 0.2, 0.1], // Niveau de zoom maximum (défaut : 28) //maxZoom: 0, // Niveau de zoom minimum (défaut : 0) //minZoom: 0, // Niveau de zoom à l'ouverture (0 : dézoomé - 20 : très zoomé) //zoom: 8, // Autoriser la rotation de la carte (défaut : true) //enableRotation: true, // Contrainde la rotation de la carte (défaut : true) // true = sans contrainte mais accrochage automatique vers 0° // nombre : nombre d'étapes possibles (4 étape = 0, 90, 180 et 270 degrés) //constrainRotation: true, // Rotation de la carte en radian dans le sens des aiguilles d'une montre (défaut : 0) //rotation: 0,*** }); // Paramétrage de la carte ////////////////////////// var map = new ol.Map({ // Identifiant de l'élément HTML où placer l'élément target: 'ol_localisation', // Couches à utiliser dans la carte // L'objet est défini plus bas layers: data_group, // Controles à utiliser dans la carte //controls:, // Paramétrage de la vue view: vue_carte, // Nombre du tuiles chargées simultanéement (défaut : 16) //maxTilesLoading: 10, // Charger les tuiles durant les animations (défaut : false) //loadTilesWhileAnimating: false, // Charger les tuiles durant les interactions (défaut : false) //loadTilesWhileInteracting: false, // Tolérance de détection des mouvement du curseur en pixel (défaut : 1) //moveTolerance: 1, });
Nous avons maintenant une carte avec un fond de plan affiché et des données (voir en plus grand) :
Ajouter des contrôles
Le but est maintenant d’avoir des boutons pour contrôler la carte (zoom, échelle, mentions, plein écran…).
Complétez vos fichiers avec ceci :
# # Cliquez sur le nom des fichiers pour en afficher le contenu. #
// Paramétrage de la carte ////////////////////////// // Modifiez simplement l'option concernant les contrôles en ajoutant les contrôles que vous voulez avoir dans votre carte (ici on ajoute tous les contrôles). var map = new ol.Map({ // Controles à utiliser dans la carte controls: [ // On reprend les paramétrages définis dans le fichier ol_control.js cont_zoom, cont_rotation, cont_zoom_sur_emprise, cont_barre_zoom, cont_mini_carte, cont_echelle, cont_position_cuseur, cont_plein_ecran, cont_mention_legale, cont_control_couche, ], });
/************************----************************/ /* Open Layers */ /* Paramétrage des contrôles */ /****************************************************/ // Ce fichier contient la définition des contrôles de la carte // Les objets que l'on retrouve dans cette configuration (avec par indentation ce qu'ils contiennent) : // ol.control.Zoom : bouton de zoom et de dézoom // ol.control.Rotate : bouton de réinitialisation de la rotation de la carte (faite avec maj+alt+clic) // ol.control.OverviewMap : mini carte // ol.layer.Tile : couche présente dans la mini carte // ol.View : paramétrage de la vue de la mini carte // ol.control.ZoomToExtent : bouton de recentrage de la carte // ol.control.ZoomSlider : slider de zoom // ol.control.ScaleLine : échelle // ol.control.MousePosition : coordonnées du pointeur // ol.control.FullScreen : bouton de passage en mode plein écran // ol.control.Attribution : mentions (crédits) // ol.control.LayerSwitcher : extension d'Open Layer permettant d'afficher une légende // Boutons de zoom var cont_zoom = new ol.control.Zoom({ // Libellé du bouton de zoom avant (défaut : '+') //zoomInLabel: '+', // Infobulle du bouton de zoom avant (défaut : 'Zoom in') zoomInTipLabel: 'Zoomer', // Libellé du bouton de zoom arrière (défaut : '-') //zoomOutLabel: '-', // Infobulle du bouton de zoom arrière (défaut : 'Zoom out') zoomOutTipLabel: 'Dézoomer', // Nombre de paliers de zoom par clic (défaut : 1) //delta: 1, // Durée du zoom en millisecondes (défaut : 250) //duration: 250, // Classe de l'élément (défaut : 'ol-zoom') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Bouton de rotation var cont_rotation = new ol.control.Rotate({ // Libellé du bouton (défaut : '⇧') //label: '⇧', // Infobulle du bouton (défaut : 'Reset rotation') tipLabel: 'Réinitialiser la rotation - Maintenez alt+shift pour tourner la carte', // Durée du zoom en millisecondes (défaut : 250) //duration: 250, // Cacher le bouton lorsque la rotation est de 0° (défaut : true) autoHide: false, // Classe de l'élément (défaut : 'ol-rotate') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Bouton de zoom sur une emprise var cont_zoom_sur_emprise = new ol.control.ZoomToExtent({ // Emprise sur laquelle zoomer // Par exemple xmin, ymin, xmax, ymax en 3857 extent: [ 516540, 5687190, 801228, 5837958 ], // Libellé du bouton (défaut : 'E') //label: 'E', // Infobulle du bouton (défaut : 'Fit to extent') tipLabel: 'Zoomer sur l\'emprise initiale', // Classe de l'élément (défaut : 'ol-zoom-extent') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Barre de zoom var cont_barre_zoom = new ol.control.ZoomSlider({ // Durée de l'animation de zoom en millisecondes (défaut : 200) //duration: 200, // Classe de l'élément (défaut : 'ol-zoomslider') //className: '', }) // Mini carte var cont_mini_carte = new ol.control.OverviewMap({ // Possibilité de replier l'élément (défaut : true) collapsible: true, // Replié au démarrage ? (défaut : true) collapsed: true, // Libellé du bouton lorsque l'élément est déplié (défaut : '«') //collapseLabel: '«', // Libellé du bouton lorsque l'élément est replié (défaut : '»') //label: '»', // Infobulle du bouton tipLabel: 'Afficher la mini-carte', // Couches à afficher dans la minicarte // Attention, la même couche ne doit pas être utilisée dans la carte // Il faut une couche spécifiquement créée pour la mini carte layers: [ data_raster_osm_minimap, ], // Vue spécifique à utiliser (défaut : EPSG:3857 avec centrage par défaut) view: new ol.View({ zoom: 13, }), // La mini carte doit-elle tourner avec la carte principale (défaut : false) rotateWithView: true, // Classe de l'élément (défaut : 'ol-overviewmap') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Echelle var cont_echelle = new ol.control.ScaleLine({ // Taille minimum en pixel (défaut : 64) //minWidth: 0, // Unité de l'échelle (défaut : 'metric') //units: '', // Classe de l'élément (défaut : 'ol-scale-line') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Position du curseur var cont_position_cuseur = new ol.control.MousePosition({ // Format des coordonnées coordinateFormat: function(coordinate) { return ol.coordinate.format(coordinate, '<span><i class="fas fa-map-marker-alt"></i> {x} ° | {y} °</span>', 6); }, // Projection des coordonnées (défaut : projection de la vue) projection: 'EPSG:4326', // Texte affiché lorsqu'aucune coordonnées n'est disponible (défaut : ' ') //undefinedHTML: ' ', // Classe de l'élément (défaut : 'ol-mouse-position') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Bouton d'affichage en plein écran var cont_plein_ecran = new ol.control.FullScreen({ // Libellé du bouton (defaut : '\u2922') //label: '\u2922', // Infobulle du bouton (défaut : 'Toggle full-screen') tipLabel: 'Passez en mode plein-écran', // Libellé du bouton lorsque du mode plein-écran (défaut : '\u00d7') //labelActive: '\u00d7', // Classe de l'élément (défaut : 'ol-full-screen') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Mentions légales var cont_mention_legale = new ol.control.Attribution({ // Possibilité de replier l'élément collapsible: true, // Etat "de repliage" au démarrage collapsed: true, // Libellé du bouton lorsque l'élément est déplié (défaut : '»') //collapseLabel: '»', // Libellé du bouton lorsque l'élément est replié (défaut : 'i') //label: 'i', // Infobulle du bouton tipLabel: 'Attributions', // Classe de l'élément (défaut : 'ol-attribution') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Controle des couches // Extension LayerSwitcher var cont_control_couche = new ol.control.LayerSwitcher({ // Infobulle du bouton tipLabel: 'Légende', // Visibilité des groupes (défaut : 'children') // 'none' : les groupes n'ont pas de case à cocher // 'children' : le changement d'état de visibilité d'un groupe change l'état de ses enfants vers le même état // 'group' : le changement d'état de visibilité d'un groupe ne change pas l'état de visibilité de ses enfants groupSelectStyle:'children' });
La carte possède maintenant des boutons pour contrôler la carte (voir en plus grand) :
Une légende est également présente et vous pouvez visualiser l’intérêt d’avoir groupé les couches : la légende affiche ces groupes.
Cependant, ces boutons possèdent un style un peu classique et surtout vous remarquerez que certains d’entre eux se superposent. La suite va nous permettre de personnaliser tout cela.
Personnalisation du style
Style des contrôles
Pour personnaliser le style des contrôles deux possibilités de modification :
- Le paramétrages des objets de ces contrôles.
- Le CSS associé à ces contrôles.
Nous allons nous aider de la police Font Awesome pour ajouter un peu de fun.
# # Cliquez sur le nom des fichiers pour en afficher le contenu. #
/* Ajoutez ces définitions à la suite de votre fichier CSS */ /* Open Layer */ /* Couleur des contrôles */ .ol-control > button, .ol-scale-line { background-color: rgba(255, 0, 0, 0.5); } .ol-control > button:focus, .ol-control > button:hover { background-color: rgba(255, 0, 0, 0.9); } /* Bouton */ .ol-control > button { font-family: "Font Awesome 5 Free"; } /* Zoom in */ .ol-control.ol-zoom button.ol-zoom-in::before { content: "\f067"; font-weight: 900; } /* Zoom out */ .ol-control.ol-zoom button.ol-zoom-out::before { content: "\f068"; font-weight: 900; } /* Bouton de rotation carte */ .ol-rotate { top: 4.5em; left: 0.5em; right: unset; transition: opacity .25s linear,visibility 0s linear } /* Bouton de retour à l'emprise initiale */ .ol-zoom-extent { top: 7em; } .ol-control.ol-zoom-extent button::before { content: "\f689"; font-weight: 900; } /* Slider de zoom */ .ol-zoomslider { top: 9.5em; background-color: rgba(255, 255, 255, 0.8); } /* Mini carte */ .ol-overviewmap { bottom: 2.5em; } .ol-control.ol-overviewmap button::before { content: "\f00d"; font-weight: 900; } .ol-control.ol-overviewmap.ol-collapsed button::before { content: "\f279"; font-weight: 400; } /* Position du cuseur */ .ol-mouse-position { position:absolute; top: unset; right: unset; bottom: 5px; left: 50%; transform: translate(-50%, 0); padding: 2px 5px; } /* Bouton mode plein écran */ .ol-control.ol-full-screen button.ol-full-screen-false::before { content: "\f108"; font-weight: 900; } .ol-control.ol-full-screen button.ol-full-screen-true::before { content: "\f00d"; font-weight: 900; } /* Mention */ .ol-attribution li { display: list-item; } .ol-control.ol-attribution button::before { content: "\f00d"; font-weight: 900; } .ol-control.ol-attribution.ol-collapsed button::before { content: "\f129"; font-weight: 900; }
// On remplace les valeurs textuelles affichées par rien : '' // On gère ces valeur via CSS // Boutons de zoom var cont_zoom = new ol.control.Zoom({ // Libellé du bouton de zoom avant (défaut : '+') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" zoomInLabel: '', // Infobulle du bouton de zoom avant (défaut : 'Zoom in') zoomInTipLabel: 'Zoomer', // Libellé du bouton de zoom arrière (défaut : '-') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" zoomOutLabel: '', // Infobulle du bouton de zoom arrière (défaut : 'Zoom out') zoomOutTipLabel: 'Dézoomer', // Nombre de paliers de zoom par clic (défaut : 1) //delta: 1, // Durée du zoom en millisecondes (défaut : 250) //duration: 250, // Classe de l'élément (défaut : 'ol-zoom') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Bouton de rotation var cont_rotation = new ol.control.Rotate({ // Libellé du bouton (défaut : '⇧') //label: '⇧', // Infobulle du bouton (défaut : 'Reset rotation') tipLabel: 'Réinitialiser la rotation - Maintenez alt+shift pour tourner la carte', // Durée du zoom en millisecondes (défaut : 250) //duration: 250, // Cacher le bouton lorsque la rotation est de 0° (défaut : true) autoHide: false, // Classe de l'élément (défaut : 'ol-rotate') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Bouton de zoom sur une emprise var cont_zoom_sur_emprise = new ol.control.ZoomToExtent({ // Emprise sur laquelle zoomer // Par exemple xmin, ymin, xmax, ymax en 3857 extent: [ 516540, 5687190, 801228, 5837958 ], // Libellé du bouton (défaut : 'E') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" label: '', // Infobulle du bouton (défaut : 'Fit to extent') tipLabel: 'Zoomer sur l\'emprise initiale', // Classe de l'élément (défaut : 'ol-zoom-extent') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Barre de zoom var cont_barre_zoom = new ol.control.ZoomSlider({ // Durée de l'animation de zoom en millisecondes (défaut : 200) //duration: 200, // Classe de l'élément (défaut : 'ol-zoomslider') //className: '', }) // Mini carte var cont_mini_carte = new ol.control.OverviewMap({ // Possibilité de replier l'élément (défaut : true) collapsible: true, // Replié au démarrage ? (défaut : true) collapsed: true, // Libellé du bouton lorsque l'élément est déplié (défaut : '«') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" collapseLabel: '', // Libellé du bouton lorsque l'élément est replié (défaut : '»') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" label: '', // Infobulle du bouton tipLabel: 'Afficher la mini-carte', // Couches à afficher dans la minicarte layers: [ data_raster_stamen_toner, ], // Vue spécifique à utiliser (défaut : EPSG:3857 avec centrage par défaut) view: new ol.View({ zoom: 13, }), // La mini carte doit-elle tourner avec la carte principale (défaut : false) rotateWithView: true, // Classe de l'élément (défaut : 'ol-overviewmap') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Echelle var cont_echelle = new ol.control.ScaleLine({ // Taille minimum en pixel (défaut : 64) //minWidth: 0, // Unité de l'échelle (défaut : 'metric') //units: '', // Classe de l'élément (défaut : 'ol-scale-line') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Position du curseur var cont_position_cuseur = new ol.control.MousePosition({ // Format des coordonnées coordinateFormat: function(coordinate) { return ol.coordinate.format(coordinate, '<span><i class="fas fa-map-marker-alt"></i> {x} ° | {y} °</span>', 6); }, // Projection des coordonnées (défaut : projection de la vue) projection: 'EPSG:4326', // Texte affiché lorsqu'aucune coordonnées n'est disponible (défaut : ' ') //undefinedHTML: ' ', // Classe de l'élément (défaut : 'ol-mouse-position') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Bouton d'affichage en plein écran var cont_plein_ecran = new ol.control.FullScreen({ // Libellé du bouton (defaut : '\u2922') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" label: '', // Infobulle du bouton (défaut : 'Toggle full-screen') tipLabel: 'Passez en mode plein-écran', // Libellé du bouton lorsque du mode plein-écran (défaut : '\u00d7') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" labelActive: '', // Classe de l'élément (défaut : 'ol-full-screen') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Mentions légales var cont_mention_legale = new ol.control.Attribution({ // Possibilité de replier l'élément collapsible: true, // Etat "de repliage" au démarrage collapsed: true, // Libellé du bouton lorsque l'élément est déplié (défaut : '»') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" collapseLabel: '', // Libellé du bouton lorsque l'élément est replié (défaut : 'i') // On gère le libellé via le CSS (pseudo-élément before) et la font "Font Awesome" label: '', // Infobulle du bouton tipLabel: 'Attributions', // Classe de l'élément (défaut : 'ol-attribution') //className: '', // Identifiant de l'élément HTML où placer l'élément //target: '', }) // Controle des couches // Extension LayerSwitcher var cont_control_couche = new ol.control.LayerSwitcher({ // Infobulle du bouton tipLabel: 'Légende', // Visibilité des groupes (défaut : 'children') // 'none' : les groupes n'ont pas de case à cocher // 'children' : le changement d'état de visibilité d'un groupe change l'état de ses enfants vers le même état // 'group' : le changement d'état de visibilité d'un groupe ne change pas l'état de visibilité de ses enfants groupSelectStyle:'children' });
Vous devriez maintenant obtenir ce résultat (voir en plus grand) :
Style des couches
Nous souhaitons maintenant ajouter un peu de couleur (style par catégorie) et de quoi identifier nos objets (étiquettes).
Nous avons vu que la définition du style d’une couche est fixe. Pour la modifier, il faut comprendre que lors de l’affichage des objets, Open Layer appelle la définition du style de la couche pour chaque objet. Ainsi, si nous modifions cette définition à la volée, pour chaque objet, il devient possible d’avoir un style dynamique, mis à jour pour chaque objet.
Pour faire tout cela, intéressons nous à l’option style
de l’objet ol.layer.Vector
(la couche de données). D’après la documentation, cette option doit avoir comme valeur un objet de type ol.style.Style
. Ce qui est intéressant c’est que cet objet peut être remplacé par une fonction qui renvoi ce type d’objet et à laquelle sera automatiquement passé deux paramètres : l’objet affiché (ainsi pour chaque objet, la fonction renverra un style spécifique) et la résolution de la vue actuellement utilisée (ainsi selon le niveau de zoom, le style peut être différent).
Nous allons donc modifier la définition du style que nous avons précédemment utilisé grâce à une fonction et utiliser le résultat de cette fonction dans notre couche :
# # Cliquez sur le nom des fichiers pour en afficher le contenu. #
// On conserve la définition du style de la donnée vecteur, ajoutez ce qui suit juste à la suite du style de la données vecteur. // Remplacez également la définition de la couche de données // On défini d'abord un style spécifique pour chaque valeur // On ne changera que la propriété image de l'objet ol.style.Style var ol_style_layer_exemple_style_specifique = { // Style par défaut 'Défaut' : new ol.style.Icon({ // Image source à utiliser src:'https://ressource.arthurbazin.com/demo/open_layer/ressource/placeholder_black.svg', // Echelle de l'image (défaut : 1) scale:0.5, // Rotation de l'icone avec la vue (défaut : false) rotateWithView: true, }), // Style pour la valeur 1 'Lucinges' : new ol.style.Icon({ // Image source à utiliser src:'https://ressource.arthurbazin.com/demo/open_layer/ressource/placeholder_blue.svg', // Echelle de l'image (défaut : 1) scale:0.5, // Rotation de l'icone avec la vue (défaut : false) rotateWithView: true, }), // Style pour la valeur 2 'Saint-Gervais' : new ol.style.Icon({ // Image source à utiliser src:'https://ressource.arthurbazin.com/demo/open_layer/ressource/placeholder_green.svg', // Echelle de l'image (défaut : 1) scale:0.5, // Rotation de l'icone avec la vue (défaut : false) rotateWithView: true, }), } // Fonction de modification du style initial function ol_style_layer_exemple_fct(feature, resolution) { // Modification de l'étiquette // On récupère l'objet ol.style.Text // On défini la valeur de la propriété "text" comme étant la valeur de l'attribut "name" de chaque objet ol_style_layer_exemple.getText().setText(feature.get('name')); // Modification de l’icône // Si la définition spécifique existe if (ol_style_layer_exemple_style_specifique[feature.get('name')] != null) { // On défini la valeur de la propriété "image" comme étant l'objet définit dans ol_style_layer_exemple_style_specifique et portant un nom égal à l'attribut "name" de chaque objet ol_style_layer_exemple.setImage(ol_style_layer_exemple_style_specifique[feature.get('name')]); } // Sinon on utilise la définition par défaut else { ol_style_layer_exemple.setImage(ol_style_layer_exemple_style_specifique['Défaut']); }; return ol_style_layer_exemple; } // Définition de la couche de données ///////////////////////////////////// // On utilise la fonction plutôt que le style initial var data_vecteur_layer_exemple = new ol.layer.Vector({ // Opacité de la couche (défaut : 1) //opacity: 1, // Visibilité de la couche (défaut : true) //visible: true, // Résolutions minimum (niveau de zoom) incluse d'affichage de la couche en unité de carte par pixel //minResolution:25, // Résolutions maximum (niveau de dézoom) exclue d'affichage de la couche en unité de carte par pixel //maxResolution:500, // Niveau de superposition de la couche (défaut : 0) //zIndex: 0, // Emprise de rendu maximum // Emprise en xmin, ymin, xmax, ymax en 3857 //extent: [], // Ordre de rendu de la couche (ordre de dessin des couches) //renderOrder: 1, // Zone en pixel autour de la carte jusqu'ou la couche sera dessinée après chaque déplacement (défaut : 100) //renderBuffer: 100, // Mode de rendu de la couche (défaut : 'vector') // 'vector' : Rendu vecteur : plus précis durant les animations mais plus lourd // 'image' : Rendu image : moins précis durant les animations mais plus léger, les point et les étiquettes tournent avec la vue //renderMode: 'vector',*** // Gestion des conflits entre les objets (défaut : false) // Lorsqu'activé, la priorité des objets est définit avec la propriété zIndex du style //declutter: false, // Extension LayerSwitcher : Titre de la couche title: 'Couche exemple', // Source de la données source: ol_source_layer_exemple, // Style de la couche // On utilise la fonction plutôt que le style initial. // L'objet à afficher et la résolution seront passés à la fonction comme arguments style: ol_style_layer_exemple_fct, })
Votre carte devrait maintenant ressembler à ça (voir en plus grand) :
Interaction avec la carte
Il est possible d’interagir avec la carte depuis « l’extérieur » de celle-ci. Par exemple, cliquer sur un bouton pour zoomer quelque part.
Pour cela, il suffit d’utiliser les nombreuses méthodes disponibles avec la carte et de les associer avec des boutons.
Dans mon exemple, je souhaite avoir deux boutons qui permettent de zoomer sur deux emplacements différents. Pour cela, nous devons modifier la vue de notre carte (variable vue_carte
du fichier ol_map.js dans notre projet) car c’est la vue qui contrôle l’emprise visualisée.
Nous allons faire deux modifications en utilisant les méthodes à disposition pour les objets ol.View
:
- Changer le zoom avec
setResolution
. - Changer la position avec
setCenter
.
# # Cliquez sur le nom des fichiers pour en afficher le contenu. #
<!-- Ajoutez ce code juste en dessous de votre carte --> <!-- Boutons de localisation de la page --> <div class="btn_localisation"> <!-- On fixe le niveau de zoom à 10 mètres par pixel : --> <!-- vue_carte.setResolution(10) --> <!-- On centre la carte sur un point dont les sont reprojetées dans le SRID de la carte car les coordonnées sont en latitude longitude : --> <!-- vue_carte.setCenter(ol.proj.fromLonLat([6.711486, 45.892829])) --> <button type="button" onclick="vue_carte.setResolution(10);vue_carte.setCenter(ol.proj.fromLonLat([6.711486, 45.892829]));">Localisation 1</button> <button type="button" onclick="vue_carte.setResolution(10);vue_carte.setCenter(ol.proj.fromLonLat([6.318435, 46.190029]));">Localisation 2</button> </div>
/* Ce code CSS n'est pas essentiel mais avoir un peu de style ne fait jamais de mal */ /* Bouton */ .btn_localisation{ margin: 20px 0px; text-align: center; } .btn_localisation button { display: inline-block; height:35px; width: 150px; margin: 0px 20px; border: 1px solid #1e2446; border-radius: 5px; font-family: 'Quicksand', sans-serif; color: #fff; background-color: #AF00FF; background-image: linear-gradient(332deg, #009FFF 0%, #AF00FF 100%); transition: all 0.4s; } .btn_localisation button:hover { background-color: rgb(125, 0, 184); background-image: linear-gradient(332deg, rgb(3, 123, 197) 0%, rgb(125, 0, 184) 100%); box-shadow: 0px 0px 10px #000; cursor: pointer; transition: all 0.4s; }
Vous devriez maintenant avoir le rendu suivant (voir en plus grand) :
Vous remarquerez qu’il est plus facile d’utiliser ce système que le contrôle « zoomer sur une emprise » pour revenir à l’emprise initiale. En effet, pour ce dernier, il faut spécifier une emprise alors que l’emprise initiale de la carte est défini par un point et une résolution.
Résolution de carte
Vous avez noté que nous parlons de « résolution » pour le niveau de zoom. En effet, il n’est pas possible de connaitre les caractéristiques des écrans qui vont afficher la carte. Ainsi, il n’est pas possible de connaitre l’échelle exacte de l’affichage final.
Ainsi, le niveau de zoom est défini par rapport à une résolution : un nombre de mètre de carte par pixel affiché à l’écran. Par exemple, dans l’exemple précédent on zoom sur un emplacement en définissant la résolution à 10 : 10 mètres de la carte par pixel affiché. Ainsi, 100 pixels de votre écran affichent 1 km.
Pour calculer l’échelle d’affichage, il faut impérativement connaitre la résolution de votre écran car c’est elle qui renseignera sur le nombre de pixel par centimètre affichés par celui-ci.
Par exemple, si votre écran possède une résolution de 150 dpi (dot per inch : point par pouce), il affiche environ 60 pixels par centimètre. Ainsi :
- Résolution de l’écran : 150 dpi : 60 pixels = 1 cm écran
- Résolution de la carte : 1 pixel = 10 m carte
- 1 cm écran = 60 pixels = 600 m carte ou 60 000 cm carte
- => Échelle = 1 : 60 000
La formule à utiliser est la suivante : Echelle = 1 : Rmap * ( Rscreen / 0,0254 )
- Rscreen : résolution de l’écran en dpi (dot per inch) ou ppp (point par pouce)
- Rmap : résolution de la carte en mètre par pixel
Exemple final
Voila un petit exemple avec un peu plus de CSS (voir en plus grand) :
Cet article vous a plu ?
N'hésitez pas à le partager, il interessera surement certains de vos contacts.
Les thèmes suivants contiennent des articles en lien avec celui-ci, allez faire un tour :
HTML et CSSJavaScriptProgrammationSIG OLOpen Layersigtuto