Tutoriel de géolocalisation en HTML5

Tutoriel Géolocalisation HTML5
Ce tutoriel a pour but de mettre en pratique pas à pas la géolocalisation en HTML5. Nous allons voir comment il est possible de récupérer les coordonnées d’un utilisateur, comment gérer les cas de succès et d’erreur avec les callbacks, comment suivre ses déplacements, et enfin toutes les informations que nous pouvons obtenir sur ses coordonnées, comme sa vitesse ou sa direction.

Avant de commencer il est important de rappeler qu’à l’heure actuelle, la géolocalisation n’est pas encore supportée par Internet Explorer. En revanche, tous les autres navigateurs modernes l’implémentent correctement. Il est possible de suivre l’évolution des fonctionnalités HTML5 prises en charge par les différents navigateurs sur le site CanIUse.com ou bien le Wiki des moteurs de rendu utilisés par les navigateurs.

Récupérer les coordonnées

Tout d’abord, nous allons créer un document HTML le plus simple possible, sans se soucier du Doctype, de la partie head et des autres détails de la structure HTML habituelle. Nous avons uniquement besoin d’exécuter du code Javascript. Voilà donc à quoi ressemble notre fichier :

geolocalisation.html

<script type="text/javascript">

</script>

Avant de chercher à utiliser la géolocalisation, il est bien entendu important de savoir si le navigateur de l’utilisateur la supporte. Pour cela on ajoute tout simplement les lignes suivantes :

	if (navigator.geolocation)
		alert("Bravo ! Votre navigateur prend en compte la géolocalisation HTML5");
	else
		alert("Dommage... Votre navigateur ne prend pas en compte la géolocalisation HTML5");

navigator.geolocation renvoie un simple booléen valant vrai ou faux selon la capacité du navigateur à utiliser la géolocalisation (… autrement dit c’est un détecteur d’IE !).
Ensuite, afin de récupérer les coordonnées, on utilise la méthode getCurrentPosition() :

	if (navigator.geolocation)
	{
		navigator.geolocation.getCurrentPosition(function(position)
		{
			alert("Latitude : " + position.coords.latitude + ", longitude : " + position.coords.longitude);
		});
	}
	else
		alert("Votre navigateur ne prend pas en compte la géolocalisation HTML5");

Cette méthode prend en paramètre une fonction de “callback” qu’elle va appeler en lui fournissant le paramètre position contenant les coordonnées. Dans l’exemple ci-dessus, on utilise une fonction anonyme afin de traiter la variable position immédiatement à la suite du code d’appel. Dans le cas où l’on souhaite un traitement plus propre et détaillé, on utilisera une fonction nommée et déclarée comme le montrent les prochains exemples.

Mais attends une seconde… On peut connaître l’emplacement de n’importe quel utilisateur avec un petit bout de code comme ça ?

Oui, à condition qu’il accepte de partager sa localisation ! Vous avez peut-être déjà remarqué le bandeau qui apparaît en haut de certaines pages (le même bandeau qui vous propose d’enregistrer un mot de passe par exemple). Afin d’accepter de partager sa localisation, un bandeau de ce type apparaît :

Barre d'autorisation de partage de géolocalisation

Sur les smartphones, c’est un pop-up équivalent qui apparaît.

Et elle apparaît quand cette barre ?

Elle apparaît dès que l’on cherche à accéder aux coordonnées de l’utilisateur. Donc par exemple lorsque vous utilisez getCurrentPosition ! Ce qui évite de demander l’autorisation inutilement à l’utilisateur. Allez, on reprend avec nos fonctions callbacks !

Utilisation des callbacks

La méthode getCurrentPosition() peut prendre un second paramètre : le callback d’erreur. C’est la fonction qui sera appelée dans les cas où :

  • L’utilisateur refuse l’autorisation d’accès à sa position
  • L’emplacement de l’utilisateur n’ait pas pu être déterminé
  • Le service de géolocalisation ne réponde pas assez vite

On utilise donc la fonction de callback pour gérer ces 3 cas :

	if (navigator.geolocation)
		navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
	else
		alert("Votre navigateur ne prend pas en compte la géolocalisation HTML5");

	function successCallback(position){
		alert("Latitude : " + position.coords.latitude + ", longitude : " + position.coords.longitude);
	});	

	function errorCallback(error){
		switch(error.code){
			case error.PERMISSION_DENIED:
				alert("L'utilisateur n'a pas autorisé l'accès à sa position");
				break;
			case error.POSITION_UNAVAILABLE:
				alert("L'emplacement de l'utilisateur n'a pas pu être déterminé");
				break;
			case error.TIMEOUT:
				alert("Le service n'a pas répondu à temps");
				break;
			}
	});

Enfin, le 3ème paramètre de getCurrentPosition() sert à indiquer certaines options particulières, écrites de la forme suivante : {nom:valeur, nom:valeur, …}.
On peut ainsi spécifier :

  • L’utilisation du GPS pour obtenir des coordonnées beaucoup plus précises
  • Un Timeout si l’on a besoin d’une réponse avant un certain délai
  • La durée de vie maximale d’une coordonnée envoyée par l’utilisateur
   navigator.geolocation.getCurrentPosition(successCallback, errorCallback, {enableHighAccuracy : true, timeout:10000, maximumAge:600000});

Les options timeout et maximumAge sont indiquées en millisecondes, donc ici, on établit un délai de 10 secondes de timeout, et une durée de vie maximale de la dernière position de l’utilisateur de 10 minutes. Par défaut le timeout vaut la valeur “Infinity” : ({timeout:Infinity}) et si maximumAge vaut 0, alors l’application demande systématiquement une mise à jour de la position de l’utilisateur.

Suivre les déplacements

Dans de nombreux cas, on aimerait mettre à jour la position de l’utilisateur si celui-ci se déplace. On pourrait penser qu’une fonctionnalité telle que celle-ci pourrait être assez lourde à mettre en place… ce n’est pas le cas ! Il suffit simplement de remplacer la ligne :

getCurrentPosition()

par :

var watchId = navigator.geolocation.watchPosition(successCallback, errorCallback);

Comme on veut permettre à l’utilisateur d’arrêter le suivi de ses déplacements, on ajoute un simple lien effectuant un appel à clearWatch().

    function stopWatch(){
		navigator.geolocation.clearWatch(watchId);
    }
<a href="#" onclick="stopWatch()">Stop Watch</a>

Enfin, si l’on souhaite pouvoir tester facilement ce code en se promenant dans la rue avec son smartphone, il faut activer l’option enableHighAccuracy pour utiliser le GPS afin d’avoir une mise à jour fréquente de la position.

Voici le code Javascript complet permettant d’afficher une nouvelle popup contenant les coordonnées chaque fois que l’utilisateur se déplace :

	if (navigator.geolocation)
		var watchId = navigator.geolocation.watchPosition(successCallback, errorCallback, {enableHighAccuracy:true});
	else
		alert("Votre navigateur ne prend pas en compte la géolocalisation HTML5");

	function successCallback(position){
		alert("Latitude : " + position.coords.latitude + ", longitude : " + position.coords.longitude);
	};	

	function errorCallback(error){
		switch(error.code){
			case error.PERMISSION_DENIED:
				alert("L'utilisateur n'a pas autorisé l'accès à sa position");
				break;
			case error.POSITION_UNAVAILABLE:
				alert("L'emplacement de l'utilisateur n'a pas pu être déterminé");
				break;
			case error.TIMEOUT:
				alert("Le service n'a pas répondu à temps");
				break;
			}
	};

    function stopWatch(){
		navigator.geolocation.clearWatch(watchId);
    }

C’est court n’est-ce pas ? Et encore, nous avons une gestion des erreurs, ainsi qu’une fonctionnalité d’arrêt de la géolocalisation ! Si on avait voulu simplifier à l’extrême on aurait pu laisser uniquement les lignes vitales :

	var watchId = navigator.geolocation.watchPosition(
	function(position){
		alert("Latitude : " + position.coords.latitude + ", longitude : " + position.coords.longitude);
	}, null, {enableHighAccuracy:true});

Je ne sais pas ce que vous en dites, mais lorsque je me suis rendu compte que 4 lignes de code Javascript pouvaient faire fonctioner un suivi de position par GPS, j’ai vraiment été bluffé. Cela montre bien la volonté du W3C de faire de l’HTML5 un nouveau standard simple à utiliser.

La vitesse ! La boussole ! L’altitude !

Si vous avez été charmés par la simplicité par la partie précédente, voilà qui devrait vous achever !
Lorsque l’on récupère la variable position afin d’obtenir la latitude grâce à position.coords.latitude, on a accès à plusieurs autres attributs :

  • position.timestamp, qui renvoie le timestamp de l’heure à laquelle a été mise à jour la position
  • position.coords.altitude, qui correspond à l’altitude de l’utilisateur
  • position.coords.accuracy, qui correspond à la précision des coordonnées
  • position.coords.altitudeAccuracy, qui correspond à la précision de l’altitude
  • position.coords.heading, qui correspond à l’angle compris entre 0 et 360° par rapport au Nord (ce n’est pas aussi précis que la boussole interne d’un smartphone)
  • position.coords.speed, qui correspond à la vitesse de l’utilisateur par rapport à sa dernière position.

Toutes ces valeurs sont remplies par le service de géolocalisation et vous n’avez absolument pas besoin de les calculer vous-même !

Pour terminer, voici la démonstration complète de tout ce que l’on vient de voir, avec une mise en page minimale :

Démonstration de géolocalisation en HTML5

Et maintenant la cerise sur le gâteau : Pour ceux qui souhaitent utiliser toutes ces informations grâce à l’API Google Maps, je vous invite à lire mon Tutoriel sur l’API Google Maps avec la géolocalisation en HTML5.

18 thoughts on “Tutoriel de géolocalisation en HTML5

  1. Article fort intéressant et très utile et proche du complet.
    Les autres articles, en français, disponibles sont rares et moins complet.
    Merci pour cette communication.

  2. il me semble que la direction et la vitesse ne sont pas standards, c’est FF qui les a rajouté non ?

    sais tu comment tester à l’avance la disponibilité de ces infos sur le navigateur ?

    • Elles font en tout cas partie de la spécification du W3C bien qu’il ne s’agisse que de l’Editor’s Draft.
      Après il est possible que ce soit Firefox qui les ait ajoutés en premier effectivement (cela dit, il est assez peu utile d’avoir la vitesse et l’orientation d’un ordinateur fixe !).

      En ce qui concerne la détection, même Modernizr ne teste pas plus que la géolocalisation dans son ensemble. Donc je suppose que pour le moment, le mieux à faire est de tester les valeurs obtenues une fois la requête GPS effectuée si tu veux vraiment savoir si la vitesse et direction sont supportées.

      Pour avoir fait plusieurs tests en situation réelle, la direction et la vitesse peuvent prendre le temps de plusieurs requêtes avant d’afficher des résultats exploitables, donc au final, ça reste quand même difficile à tester.

      • Bonjour,
        dans le cas d`aucune connection internet dispo :
        pensez vous qu`il soit possible de developper un logiciel GPS utilisant des cartes raster en tuile( tiles) en HTML5, le site internet etant entierement charge dans le PC ?

        Bernard

        • Salut Bernard,

          Il me semble que le GPS des téléphones est indépendant de la connexion internet. Je pense donc que c’est possible, mais uniquement avec la précision GPS.
          A vérifier cependant ! Ça peut se tester assez facilement.

  3. Salut,

    Tout d’abord, merci pour ce tutoriel. Comme dit plus haut, c’est rare d’avoir un article aussi complet en français.
    J’ai testé avec mon iphone et ça fonctionne niquel.

    Juste une question, je souhaite que ça ajoute sur ma bdd mysql la lattitude et la longitude (par exemple toutes les 15 secondes) mais je n’arrive pas à lier le script avec le php.
    Peux tu me dire en une ligne comment faire ?

    Merci d’avance,
    Guillaume

    • Dans tous les cas, si tu souhaites sauvegarder les infos de géolocalisation côté serveur, il faudra que tu utilises des appels AJAX.
      Tu peux par exemple exécuter un appel AJAX toutes les 30 secondes grâce à la fonction Javascript setTimeOut, qui utilise également un « callback ».
      Dans ce callback tu placeras l’appel AJAX, réalisé avec jQuery par exemple.
      Le reste du travail sera alors à faire côté serveur !

  4. Bonjour.
    Merci pour ce tutoriel très clair. Mais comment faire pour obtenir la position dans une variable globale ? Je n’arrive irrémadiablement pas à faire sortir une variable d’une fonction callback
    Mon code :

    function myPosition(){
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
    function(position) { myPos = {"Lat":position.coords.latitude, "Lon":position.coords.longitude} },
    function() { myPos = {"Lat": 48.856667, "Lon": 2.351944} }, //une position par défaut en cas d’échec
    {enableHighAccuracy : true});
    }
    return myPos;
    }
    alert(myPosition().Lat);
    alert(myPosition().Lon);

    Une idée ?

    • Salut Julien,

      Il est impossible de faire appel au résultat d’une fonction de callback immédiatement après l’avoir déclenchée, puisque par définition, cette fonction va prendre du temps, et que son résultat ne sera disponible que quelques secondes plus tard (bien après que le reste de ton code soit exécuté donc).

      Si tu veux récupérer une valeur obtenue dans une fonction de callback dans une variable globale, il suffit de la mettre à jour avec la nouvelle valeur dans la fonction de callback.

      Dans l’idée ça donnerait quelque chose comme ça :

      var myPos = {};
      
      function myPosition(){
        getCurrentPosition(function(position){
          myPos = position;
        }
      }
      
  5. bonjour!
    je ne parviens pas malgré la fonction call back à afficher ma position sauf avec google chrome avec les autres navigateurs le marqueur n est pas affiché , et j ‘ai une erreur sptipulant que le « Le service n’a pas répondu à temps »
    alors y a t il moyen d y remedier

    • La géolocalisation est parfois capricieuse si on la lance trop souvent avec un navigateur (surtout si la page est ouverte sans protocole HTTP, directement avec le protocole file://). Pour tes tests, essaye en localhost, et tente de complètement fermer puis ré-ouvrir Firefox si la géoloc semble ne plus passer après plusieurs tentatives.

  6. Bonjour,

    Je cherche à réinitialiser les données de géolocalisation.
    Explication : si un visiteur refuse une première fois la géolocalisation, les Smartphones comme l’iPhone conservent ce choix et ne permettent pas toujours une nouvelle demande de géolocalisation, alors même que celle-ci est déclenchée par un clic sur un bouton .
    J’ai essayé de mettre à jour le timeout , de réinitialiser tout ce qui peut l’être sans succès. Même lorsque je vide le cache de mon tel je reste sur le code PERMISSION_DENIED.

    S’il y a des idées, je prends volontiers . Merci

    • Salut Tom,

      Si l’utilisateur refuse de partager sa position, il est normal que les smartphones n’affichent pas à nouveau des popups intrusifs, ce qui nuirait à l’expérience utilisateur. Selon moi si tu obtiens un code PERMISSION_DENIED, tu dois demander à l’utilisateur de débloquer ton site dans ses paramètres s’il a refusé le partage de sa position. Imagine un site qui demande en permanence le partage de la position, ce serait un enfer pour l’utilisateur (comme une boucle infinie d’alert()), je pense donc qu’ils ont préféré garder le dernier choix en mémoire pour ne pas déranger l’utilisateur.

      Je suppose que cela ne t’arrange pas mais je n’ai pas d’autre solution à te proposer !

      • D’abord merci beaucoup pour la réponse si rapide.

        C’est aussi le raisonnement que j’ai tenu. Et l’attribut error est en readonly donc pas moyen de jouer avec l’API.
        Ceci dit le comportement varie selon les navigateurs. Sous Firefox par exemple, un clique relance le script sans problème. A vrai dire sur le même mobile j’ai eu des comportements différents.

        Une solution, plutôt une astuce: passer par un confirm en js avant de lancer la géoloc: inconvénient 2 pop up successifs .Ou passer par une autre fonction de geoloc google ou constructeur (pas testé mais en théorie …)

  7. Bonjour,

    Merci pour ce billet fort utile que je découvre avec beaucoup de retard, je me suis permis d’en copier/coller des extraits sur mon blog, j’espère que c’est une forme de partage autorisée.

    Merci encore.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>