X

Openlayers : zoom sur la géolocalisation

Le script du jour a pour objectif de géolocaliser le visiteur d’une page puis de zoomer sur sa localisation avec une cartographie dynamique. Le résultat de ce tutoriel est disponible sur cette demo*. On reviendra sur le vaste thème de la géolocalisation puisque de nombreux outils existent pour cibler l’utilisateur. Est-il préférable d’utiliser l’API de géolocalisation de Google Maps, du navigateur client, etc? Géocoder l’IP du visiteur est aussi une solution.

Ici, on utilise l’API d’Openlayers (v 3.20) pour cibler l’utilisateur. La classe de ol.Geolocation d’Openlayers utilise en fait l’API Geolocation du HTML5. Plusieurs propriétés de l’objet sont disponibles : accuracy, altitude, speed, position, etc. Le déclencheur change scrute les différentes modifications liées aux propriétés et la méthode get (getPosition() par exemple) permet d’obtenir les informations souhaitées comme l’altitude, la position, la vitesse de déplacement, l’orientation et autres.

Pour fonctionner la classe de géolocalisation n’a pas besoin de la déclaration de l’objet Map. Dans le script suivant, on déclare la géolocalisation puis on obtient la position et la précision (Accuracy) de la cible.

<!DOCTYPE html>
<html>
	<head>
		<title>Zoom sur la géolocalisation</title>
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
		<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
		<link rel="stylesheet" href="http://openlayers.org/en/v3.20.1/css/ol.css" type="text/css">
		<script src="http://openlayers.org/en/v3.20.1/build/ol.js"></script>	
	</head>
	<body>
		<div>
			Précision : <span id="precision"></span> m | Position : <span id="latitude"></span>° ; <span id="longitude"></span>°
		</div>
		<script>
			// On déclare la géolocalisation
			var geolocation = new ol.Geolocation({
			  // On déclenche la géolocalisation
			  tracking: true,
			}); 
			// On scrute les changements des propriétés
			geolocation.on('change', function(evt) {
			  var precision = geolocation.getAccuracy();
			  $("#precision").html(precision);
			  var position = geolocation.getPosition();
			  $("#latitude").html(position[1]);
			  $("#longitude").html(position[0]);
			});
			// On alerte si une erreur est trouvée
			geolocation.on('error', function(erreur) {
				alert('Echec de la géolocalisation : ' +erreur.message);       
			});
		</script>
	</body>
</html>

On note que le résultat de la méthode getPosition() est un tableau avec deux éléments : la longitude et la latitude.

Pour la suite, « on ne réinvente pas l’eau chaude », donc le code s’inspire d’un exemple disponible sur le site d’Openlayers. Avec la position, on ajoute un objet géographique à un vecteur situé aux coordonnées trouvées sur la carte.  Voici le code Javascript modifié :

<script>
	// Vue
	var view = new ol.View({
		center: [0, 0],
		zoom: 2,
	});
	// Carte avec un fonds de carte
	var map = new ol.Map({
		layers: [
		  new ol.layer.Tile({
			source: new ol.source.OSM()
		  })
		],
		target: 'carte',
		view: view
	});
	// Objet géographique de la position de géolocalisation
	var ObjPosition = new ol.Feature();
	// Attribution d'un style à l'objet
	ObjPosition.setStyle(new ol.style.Style({
		image: new ol.style.Circle({
			radius: 6,
			fill: new ol.style.Fill({
				color: '#3399CC'
			}),
			stroke: new ol.style.Stroke({
				color: '#fff',
				width: 2
			})
		})
	}));
	// Géolocalisation
	var geolocation = new ol.Geolocation({
	  // On déclenche la géolocalisation
	  tracking: true,
	  // Important : Projection de la carte
	  projection: view.getProjection()
	}); 
	// On scrute les changements des propriétés
	geolocation.on('change', function(evt) {
		var precision = geolocation.getAccuracy();
		$("#precision").html(precision);
		var position = geolocation.getPosition();
		// On transforme la projection des coordonnées
		var newPosition=ol.proj.transform(position, 'EPSG:3857','EPSG:4326');
		$("#latitude").html(newPosition[1]);
		$("#longitude").html(newPosition[0]);
		// Attribution de la géométrie de ObjPosition avec les coordonnées de la position
		ObjPosition.setGeometry( position ? new ol.geom.Point(position) : null );
	});
	// On alerte si une erreur est trouvée
	geolocation.on('error', function(erreur) {
		alert('Echec de la géolocalisation : ' +erreur.message);       
	});
	// Source du vecteur contenant l'objet géographique
	var sourceVecteur = new ol.source.Vector({
			features: [ObjPosition]
	});
	// Couche vectorielle 
	var vecteur = new ol.layer.Vector({
		map: map,
		source: sourceVecteur
	});
</script>

En remarque, comme on ajoute un fonds de carte OpenStreetMap (OSM()), la projection de la carte change et celle des coordonnées de la méthode getPosition() aussi. D’ailleurs, dès la déclaration de la carte, on est obligé de définir la projection de la variable geolocalisation par :

projection: view.getProjection()

De plus, pour obtenir des coordonnées en degrés, on transforme la projection de la variable position.

Enfin, lorsque le vecteur est chargé, on zoom sur son emprise. Voici le code final :

<!DOCTYPE html>
<html>
	<head>
		<title>Zoom sur la géolocalisation</title>
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
		<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
		<link rel="stylesheet" href="http://openlayers.org/en/v3.20.1/css/ol.css" type="text/css">
		<script src="http://openlayers.org/en/v3.20.1/build/ol.js"></script>	
	</head>
	<body>
		<div>
			Précision : <span id="precision"></span> m | Position : <span id="latitude"></span>° ; <span id="longitude"></span>°
		</div>
		<div id="carte"></div>
		<script>
			// Vue
			var view = new ol.View({
				center: [0, 0],
				zoom: 2,
				maxZoom: 19,
			});
			// Carte avec un fonds de carte
			var map = new ol.Map({
				layers: [
				  new ol.layer.Tile({
					source: new ol.source.OSM()
				  })
				],
				target: 'carte',
				view: view
			});
			// Objet géographique de la position de géolocalisation
			var ObjPosition = new ol.Feature();
			// Attribution d'un style à l'objet
			ObjPosition.setStyle(new ol.style.Style({
				image: new ol.style.Circle({
					radius: 6,
					fill: new ol.style.Fill({
						color: '#3399CC'
					}),
					stroke: new ol.style.Stroke({
						color: '#fff',
						width: 2
					})
				})
			}));
			// Géolocalisation
			var geolocation = new ol.Geolocation({
			  // On déclenche la géolocalisation
			  tracking: true,
			  // Important : Projection de la carte
			  projection: view.getProjection()
			}); 
			// On scrute les changements des propriétés
			geolocation.on('change', function(evt) {
				var precision = geolocation.getAccuracy();
				$("#precision").html(precision);
				var position = geolocation.getPosition();
				// On transforme la projection des coordonnées
				var newPosition=ol.proj.transform(position, 'EPSG:3857','EPSG:4326');
				$("#latitude").html(newPosition[1]);
				$("#longitude").html(newPosition[0]);
				// Attribution de la géométrie de ObjPosition avec les coordonnées de la position
				ObjPosition.setGeometry( position ? new ol.geom.Point(position) : null );
			});
			// On alerte si une erreur est trouvée
			geolocation.on('error', function(erreur) {
				alert('Echec de la géolocalisation : ' +erreur.message);       
			});
			// Source du vecteur contenant l'objet géographique
			var sourceVecteur = new ol.source.Vector({
					features: [ObjPosition]
			});
			// Couche vectorielle 
			var vecteur = new ol.layer.Vector({
				map: map,
				source: sourceVecteur
			});
			// Zoom sur l'emprise du vecteur
			sourceVecteur.once('change', function(evt){
				// On vérifie que la source du vecteur sont chargés
				if (sourceVecteur.getState() === 'ready') {
					// On vérifie que le veteur contient au moins un objet géographique
					if (sourceVecteur.getFeatures().length >0) {
						// On adapte la vue de la carte à l'emprise du vecteur
						map.getView().fit(sourceVecteur.getExtent(), map.getSize());
					}
				}
			});
		</script>
	</body>
</html>

On ajoute un zoom maximum maxZoom dans la vue de la carte car la faible emprise du point de la géolocalisation a pour effet de diminuer fortement l’échelle de la carte.

Je te laisse ajouter l’objet géographique de la précision au vecteur. Si tu as des questions, on y répondra avec plaisir!

En résumé, on a codé un zoom sur la géolocalisation d’un visiteur grâce à l’API d’Openlayers. Comme évoqué en introduction, ce sujet sera largement approfondi dans Geomatick.

* Sur Google Chrome, seule la géolocalisation dans un contexte sécurisé (SSL) fonctionne ou bien entendu avec l’API de Google Maps…

Partager l'article
Florian Delahaye: Passionné de Géomatique
Related Post