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…