Accès direct au résultat
Le problème
Savoir où on est et le montrer sur une carte interactive.
La solution
Pour réaliser une telle application 100% web il nous faut :
- utiliser un système de cartographie libre de droits et simple à mettre en œuvre comme l'est OSM,
- utiliser les APIs de localisation javascript fournies en conformité avec les spécifications du HTML5,
- écrire la page web assemblant le tout.
La carte OSM (ou OpenStreetMap)
Ce système de cartographie coopératif est exploitable par la librairie OpenLayers qui est écrite en javascript. Celle ci permet :
- de créer un carte mondiale et de se positionner sur celle-ci,
- de manipuler celle-ci aussi bien avec un dispositif tactile qu'avec le traditionnel tandem clavier/souris,
- de placer sur la carte des points de repère à partir de leurs coordonnées.
Ceci devrait convenir à notre usage, mais avant de produire du code applicatif nous allons créer notre propre librairie exploitant OpenLayers.
Cette librairie devra :
- accepter un tableau de points à visualiser, chaque point étant indiqué par :
- une image au format png ou mieux en svg ainsi que ses dimensions et sa position,
- ses coordonnées (latitude et longitude),
- une description textuelle,
- un nom (le nom localisation sera utilisé pour déplacer le point à localiser par la suite),
- fournir les contrôles de zoom et de déplacement nécessaires à l'exploration de la carte,
- fournir une méthode de dessin qui sera exécutée en fin de chargement (sur onload),
- fournir une méthode déplacement d'un point move_point(lon, lat, cap) qui sera appliquée de façon asynchrone au point nommé localisation.
Cette librairie nommée utils_osm_pts sera placée dans le fichier es/utils_osm_pts.js et sera donc composée des éléments suivants :
la fonction utils_osm_pts(pts_list)
cette fonction correspond à la déclaration de l'objet utils_osm_pts qui constitue le seul élément de cette librairie.
Elle comporte donc :
- la déclaration des variables map et ptLoc internes à la librairie et nécessaires à son fonctionnement,
- la méthode de dessin draw_map,
- la méthode de déplacement d'un point localisation nommée move_point(lon, lat, cap),
- l'exécution du dessin au chargement.
function utils_osm_pts(pts_list) {
var map; // objet carte utile pour passage de paramètres entre les 2 fonctions
var ptLoc; // le point à déplacer créé par draw_map() et manipulé par move_point()
// dessin de la carte
function draw_map() {
...
...
...
}
// déplacement du point "localisation" sur la carte
this.move_point = function(lon, lat, head, follow) {
...
...
...
}
// exécution du dessin en fin de chargement
window.addEventListener('load', draw_map, false);
}
La méthode draw_map(pts_list)
Cette méthode est une méthode privée, c'est-à-dire uniquement exploitable dans cette librairie.
Elle est en charge de :
- dessiner la carte dans l'élément HTML identifié par map,
- positionner les contrôles,
- positionner les points transmis par pts_list.
function draw_map() {
// création de la carte avec les contôles associés
map = new OpenLayers.Map({
div: "map",
controls:[new OpenLayers.Control.Zoom(),
new OpenLayers.Control.KeyboardDefaults(),
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.ScaleLine({bottomOutUnits: ''})]
});
map.addLayer(new OpenLayers.Layer.OSM());
// création du plan contenant les points de repère
refpts_layer = new OpenLayers.Layer.Vector("pts_list", {projection: "EPSG:4326"});
// création des contres des points afin qu'ils soient cliquables
var selectMarkerControl = new OpenLayers.Control.SelectFeature(refpts_layer, {
// fonction invoquée lors d'une séléction (clic impair) sur un point
onSelect: function(feature) {
var le_popup = new OpenLayers.Popup.FramedCloud("Popup",
feature.attributes.lonlat,
null,
feature.attributes.description,
null,
true);
feature.popup = le_popup;
map.addPopup(le_popup);
},
// fonction invoquée lors d'une séléction (clic pair) sur un point
onUnselect: function(feature) {
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
},
// acceptation de plusieurs points simultanément sélectionné
multiple: true,
// comportement bistable par clic (ou touch)
toggle: true,
});
// mise en place des contres et du plan de points
map.addControl(selectMarkerControl);
selectMarkerControl.activate();
map.addLayer(refpts_layer);
// dessin des points transmis
for (var i = 0; i < pts_list.length; i++) {
var pt = pts_list[i];
var LonLat = new OpenLayers.LonLat(pt.lon, pt.lat).transform("EPSG:4326", map.getProjectionObject());
var ptGeo = new OpenLayers.Geometry.Point(pt.lon, pt.lat);
ptGeo.transform("EPSG:4326", map.getProjectionObject());
map.setCenter(LonLat);
var laFeature = new OpenLayers.Feature.Vector(ptGeo,
{description:pt.descr, lonlat: LonLat},
{externalGraphic: pt.icon_url,
graphicWidth: pt.icon_width,
graphicHeight: pt.icon_height,
graphicXOffset: pt.icon_shiftX,
graphicYOffset: pt.icon_shiftY,
graphicOpacity: pt.opacity,
rotation: pt.rotation,
title: pt.title});
refpts_layer.addFeatures(laFeature);
if (pt.showPopup) selectMarkerControl.select(laFeature);
if (pt.name == 'localisation') {
// le point localisé sera rendu accéssible par la fonction de déplacement asynchrone
ptLoc = laFeature;
}
}
// ajustement de la carte à la zone couvrant les poins visualisés
map.zoomToExtent(refpts_layer.getDataExtent());
}
La méthode move_point(lon, lat, cap, follow)
Cette méthode est une méthode publique, c'est-à-dire exploitable en dehors de cette librairie.
Elle est en charge de :
- modifier les coordonnées d'un point (latitude et longitude),
- modifier l'orientation d'un point (cap ou
head
), - faire en sorte de suivre l'évolution du point (en restant centré dessus) par le dernier argument follow=true.
this.move_point = function(lon, lat, head, follow) {
var LonLat = new OpenLayers.LonLat(lon, lat).transform("EPSG:4326", map.getProjectionObject());
ptLoc.move(LonLat);
ptLoc.attributes.lonlat = LonLat;
ptLoc.style.rotation = head;
if(follow) {
map.setCenter(LonLat,map.zoom);
map.zoomToExtent(refpts_layer.getDataExtent());
}
}
Notre librairie est ainsi terminée, passons à la partie contrôle de le position.
utiliser les API de localisation
Pour piloter le point de notre position nous allons utiliser les fonctions javascript suivantes :
- la fonctions navigator.geolocation.watchPosition(success, error, options) qui se comporte ainsi :
- si la localisation est accessible la fonction success sera périodiquement exécuté (selon les déplacement constatés),
- en cas d'erreur la fonction error sera exécuté (problème de droits par exemple),
- l'objet options permet de configurer finement la localisation (précision
timeout
...)
- la fonction success invoquera move_point() en charge du suivi du point.
function success(pos) {
var lat = pos.coords.latitude;
var lon = pos.coords.longitude;
var head = pos.coords.heading;
var alti = pos.coords.altitude;
utils_osm.move_point(lon, lat, head, false);
// on affiche le cap uniquement si l'appareil le supporte
if (head) document.getElementById('cap').textContent = parseFloat(head).toFixed(2)+'°';
else document.getElementById('cap').textContent = 'inconnu';
// on affiche l'altitude uniquement si l'appareil le supporte
if (alti) document.getElementById('alti').textContent = parseFloat(alti).toFixed(0)+'m';
else document.getElementById('alti').textContent = 'inconnu';
};
function error(err) {
alert('ERROR(' + err.code + '): ' + err.message);
}
options = {
enableHighAccuracy: false,
timeout: 60000,
maximumAge: 0,
}
function RunLocation() {
if (navigator.geolocation) {
navigator.geolocation.watchPosition(success, error, options);
} else {
alert("Votre navigateur ne prend pas en compte la géolocalisation HTML5");
}
}
// on lance le suivi de la position une fois la page chargée.
window.addEventListener('load', RunLocation, false);
}
Ce code javascript sera placée dans le fichier es/geoloc.js.
Maintenant il n'y a plus qu'a réaliser la page HTML contenant le code pour agglomérer le tout.
Le document HTML
Ce document doit donc contenir :
- un lien vers la librairie publique http://openlayers.org/api/OpenLayers.js,
- un lien vers le fichier es/utils_osm_pts de la librairie utils_osm_pts précédemment créée,
- un lien vers le fichier es/geoloc.js précédemment créé,
- un élément de type div id="map",
- la déclaration des points de repère,
- un lien vers une feuille de style afin d'avoir un résultat présentable.
La feuille de style css/geoloc.css
Celle-ci s'adaptera aux dispositifs de petite taille (< 160mm).
body {background-color:#888}
body>h1 {
width:100%;
position:absolute;
text-align:center;
color:#FFF;
margin-left:-50%;
top:50%;
left:50%;
right:0;
bottom:0;
}
body>h2 {
background-color:rgba(255,255,255,0.5);
width:auto;
position:absolute;
margin:0 auto;
top:1em;
right:1em;
z-index:10;
border:solid 0.1ex rgba(255,255,0,0.6);
border-radius:0.2em;
}
body>h2>em {
color:#800;
}
#map {
top:0;
left:0;
bottom:0;
right:0;
position:
fixed;
}
@media handheld, screen and (max-width: 160mm), screen and (max-device-width: 160mm) {
body {
font-size:200%;
font-size:6vw;
}
body>h2 {
font-size:300%;
font-size:10vw;
top:0.1em;
right:0.1em;
}
}
Le document HTML
Il intègre donc l'ensemble des librairies javascript et feuilles de style css ainsi que la définition de 2 points dont un correspondra à notre position.
body {background-color:#888}<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>Pour vous situer sur terre...</title>
<link rel="icon" type="images/png" href="icons/pieton.svg" />
<link rel="stylesheet" type="text/css" href="css/geoloc.css" />
<script>
var ref_points = [
{lon: 1.446,
lat: 43.59,
icon_url: 'icons/pieton.svg',
name: 'localisation',
icon_width: '2em',
icon_height: '2em',
icon_shiftX: 0,
icon_shiftY: 0,
descr: '<div id="bul2"><em>Vous</em> êtes ici...</a></div>',
title: 'Vous'},
{lon: 1.44608,
lat: 43.5955,
icon_url: 'icons/logo_ven_loc.svg',
icon_width: '2em',
icon_height: '2em',
icon_shiftX: 0,
icon_shiftY: 0,
descr: '<div id="bul1"><a href="http://www.vous-et-nous.eu" title="Nous"><em>Nous</em> sommes là</a></div>',
title: 'Nous'}
];
</script>
<script type="text/javascript" src="http://openlayers.org/api/OpenLayers.js"></script>
<script type="text/javascript" src="es/utils_osm_pts.js"></script>
<script type="text/javascript" src="es/geoloc.js"></script>
</script>
</head>
<body>
<h1>Assistance à la localisation</h1>
<h2>cap <em id="cap">--</em><br/>
altitude <em id="alti">--</em></h2>
<div id="map"></div>
</body>
</html>
Et c'est fini, il n'y a plus qu'a charger la page de localisation ainsi réalisée dans un navigateur et jouer avec... mais attention : la localisation à partir du navigateur doit être activée, par défaut celle-ci est souvent désactivée pour des raisons de confidentialité !