Prendre un thé
Tapoter des doights
Monsieur fantôme
Quelle heure est-il ?
BazinGa's Tips & tuto IT
BazinGa's - Tips & tuto IT

Open Layer – Guide de démarrage rapide

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' ou 1234
  • 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 cartographiques
  • view: 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égales
  • ol.control.FullScreen – Mode plein écran
  • ol.control.MousePosition – Position de la souris
  • ol.control.OverviewMap – Mini carte
    • layers: ol.layer.Base – Couches de données cartographique
    • view: ol.View – Vue (emprise, rotation…)
  • ol.control.Rotate – Rotation de la carte
  • ol.control.ScaleLine – Echelle
  • ol.control.ZoomSlider – Barre de zoom
  • ol.control.ZoomToExtent – Emprise initiale
  • ol.control.Zoom – Zoom avant/arrière

ol.layer.Base

Détails

Classe de base

Couche de données cartographiques

Classes dérivées et propriétés :

  • ol.layer.Image – Couche de type image
  • ol.layer.Tile – Couche tuilée
  • ol.layer.Vector – Couche vecteur mise à jour à chaque image
  • ol.layer.VectorImage – Couche vecteur mise à jour hors animation
  • ol.layer.VectorTile – Couche vecteur tuilée
  • ol.layer.Graticule – Quadrillage
  • ol.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ée
    • ol.source.ImageArcGISRest – Service ArcGIS Rest
    • ol.source.ImageCanvas
    • ol.source.ImageMapGuide – Mapguide server
    • ol.source.ImageStatic – Simple image statique
    • ol.source.ImageWMS – Serveur WMS
    • ol.source.Raster – Raster créé à la volée à partir d’autres données
  • ol.source.Tile – Source de type image tuilée
    • ol.source.BingMaps – Image tuilée Bing Maps
    • ol.source.IIIF – Image tuilée IIF Image API
    • ol.source.TileArcGISRest – Image tuilée ArcGIS Rest
    • ol.source.TileJSON – Image tuilée JSON
    • ol.source.TileWMS – Image tuilée de serveur WMS
    • ol.source.WMTS – Image tuilée de serveur WMTS
    • ol.source.XYZ – Image tuilée au format XYZ
    • ol.source.Zoomify – Image tuilée au format Zoomify
    • ol.source.VectorTile – Données vecteur tuilées
    • ol.source.UTFGrid – Données d’interaction UTFGrid
    • tileGrid: ol.tilegrid.TileGrid – Format de la grille de tuilage
  • ol.source.Vector – Source de type vecteur
  • 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 JSON
    • ol.format.EsriJSON
    • ol.format.GeoJSON
    • ol.format.TopoJSON
  • ol.format.MVT – Format MVT de MapBox
  • ol.format.TextFeature – Données au format texte
    • ol.format.IGC
    • ol.format.Polyline – Format de données encodées par algorithme Polyline
    • ol.format.WKT – Données en Well Known Text
  • ol.format.XMLFeature – Données au format XML
    • ol.format.GPX
    • ol.format.KML
    • ol.format.OSMXML
    • ol.format.WFS
    • ol.format.WMSGetFeatureInfo

ol.style.Style

Détails

Stylisation des couches de données vecteur

Propriétés :

ol.geom.Geometry

Détails

Classe de base

Formes géométriques

Classes dérivées et propriétés :

  • ol.geom.GeometryCollection – Collection de géométries
  • ol.geom.Point – Point
    • coordinates: ol.coordinate
  • ol.geom.MultiPoint – Multipoint
    • coordinates: ol.coordinate
  • ol.geom.LinearRing – Contour circulaire
    • coordinates: ol.coordinate
  • ol.geom.LineString – Ligne
    • coordinates: ol.coordinate
  • ol.geom.MultiLineString – Multiligne
  • ol.geom.MultiPolygon Multipolygone
  • ol.geom.Polygon – Polygone
    • coordinates: ol.coordinate
  • ol.geom.Circle – Forme circulaire
    • center: 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.Fill

Détails

Remplissage

Propriétés :

  • color: ol.color

ol.style.Stroke

Détails

Contour vecteur

Propriétés :

  • color: ol.color

ol.style.Text

Détails

Etiquette de l’objet

Utilisé par :

Propriétés :

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 Stamen - Toner
////////////////////////////////////////////

var data_raster_stamen_toner = new ol.layer.Tile({
	source: new ol.source.Stamen({
		layer: 'toner'
	}),
	// 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: 'Stamen - Toner',
	// 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',
})


/************************----************************/
/*                   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_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')
	//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

50%