Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
JavaScript

L'API de géolocalisation

Apprenez à obtenir la position de l'utilisateur avec l'API de géolocalisation du navigateur : contexte sécurisé et permissions, getCurrentPosition et ses options, gestion des trois erreurs, exemple co...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Apprenez à obtenir la position de l'utilisateur avec l'API de géolocalisation du navigateur : contexte sécurisé et permissions, getCurrentPosition et ses options, gestion des trois erreurs, exemple complet « Où suis-je ? » avec lien vers la carte, utilisation avec async/await, suivi d'un déplacement avec watchPosition et calcul de distance, API Permissions, nouvel élément HTML geolocation, vie privée et bonnes pratiques. Avec des activités corrigées.
  1. Objectifs

    • Comprendre ce qu'est une API du navigateur et la notion de contexte sécurisé.
    • Obtenir la position de l'utilisateur avec getCurrentPosition() et gérer ses erreurs.
    • Suivre un déplacement avec watchPosition() et calculer une distance.
    • Transformer l'API en promesse pour l'utiliser avec async/await, et respecter la vie privée de l'utilisateur.
  2. Les API du navigateur : rappel

    • Le langage JavaScript (ECMAScript) ne sait ni afficher une page, ni localiser un téléphone. Ces services sont fournis par le navigateur sous forme d'API Web: le DOM, fetch, le localStorage (chapitre 20), et celles de ce chapitre.
    • Beaucoup d'API sensibles (position, presse-papiers, notifications, caméra…) ne fonctionnent que dans un contexte sécurisé: une page servie en HTTPS, ou sur localhost / 127.0.0.1 pendant le développement. Avec Live Server (http://127.0.0.1:5500), tout fonctionne.
    • Elles sont presque toutes soumises à une permission que l'utilisateur peut accorder ou refuser. Votre code doit toujours prévoir le refus.
    • Pour savoir si une API est utilisable partout, consultez sa fiche sur MDN: le badge Baseline indique qu'elle fonctionne dans tous les navigateurs récents.
  3. Qu'est-ce que l'API de géolocalisation ?

    • Elle donne la position géographique de l'appareil : latitude, longitude et précision en mètres.
    • Le navigateur combine plusieurs sources : le GPS (précis, surtout sur téléphone), les réseaux Wi-Fi et les antennes voisines, ou l'adresse IP (peu précise, à l'échelle d'une ville).
    • On y accède par l'objet navigator.geolocation, qui propose trois méthodes : getCurrentPosition(), watchPosition() et clearWatch().
    • Cas d'usage : météo locale, magasin ou centre le plus proche, itinéraire, suivi d'une course, pointage de présence sur un lieu de stage…

    Fonctionnement de l'API de géolocalisation : demande, autorisation, succès ou erreur

  4. Obtenir la position : getCurrentPosition()

  5. navigator.geolocation.getCurrentPosition(succes, echec, options);
  • succes(position): fonction appelée quand la position est connue. L'objet reçu contient position.coords (latitude, longitude, accuracy en mètres, et parfois altitude, speed, heading) et position.timestamp.
  • echec(erreur): fonction appelée en cas de problème. erreur.code vaut 1 (refus de l'utilisateur), 2 (position indisponible) ou 3 (délai dépassé).
  • options (facultatif) :
OptionValeur par défautRôle
enableHighAccuracyfalsetrue demande la meilleure précision (GPS) : plus lent et consomme plus de batterie.
timeoutInfinityTemps maximal d'attente en millisecondes avant l'erreur 3.
maximumAge0Âge maximal (ms) d'une position déjà en mémoire que l'on accepte de réutiliser.
  • Exemple complet : « Où suis-je ? »

  • La page affiche un bouton. Au clic, elle demande la position, l'affiche, et propose un lien vers la carte OpenStreetMap.

    index.html:

    <!doctype html>
    <html lang="fr">
      <head>
        <meta charset="utf-8" />
        <title>Où suis-je ?</title>
        <script src="geo.js" defer></script>
      </head>
      <body>
        <h1>Où suis-je ?</h1>
        <button id="btn-localiser" type="button">📍 Me localiser</button>
        <p id="statut"></p>
        <ul id="infos"></ul>
        <a id="carte" href="#" target="_blank" rel="noopener" hidden>Voir sur la carte</a>
      </body>
    </html>

    geo.js:

    const bouton = document.getElementById("btn-localiser");
    const statut = document.getElementById("statut");
    const infos = document.getElementById("infos");
    const carte = document.getElementById("carte");
    
    function ajouterInfo(libelle, valeur) {
      const li = document.createElement("li");
      li.textContent = `${libelle} : ${valeur}`;
      infos.append(li);
    }
    
    function succes(position) {
      const { latitude, longitude, accuracy } = position.coords;
      statut.textContent = "Position trouvée ✅";
      infos.replaceChildren();
      ajouterInfo("Latitude", latitude.toFixed(5));
      ajouterInfo("Longitude", longitude.toFixed(5));
      ajouterInfo("Précision", `± ${Math.round(accuracy)} m`);
      ajouterInfo("Heure", new Date(position.timestamp).toLocaleTimeString("fr-FR"));
      carte.href = `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=16/${latitude}/${longitude}`;
      carte.hidden = false;
    }
    
    function echec(erreur) {
      const messages = {
        1: "Accès refusé : autorisez la localisation dans les réglages du site.",
        2: "Position indisponible (GPS, Wi-Fi ou réseau introuvable).",
        3: "Délai dépassé : réessayez.",
      };
      statut.textContent = messages[erreur.code] ?? erreur.message;
    }
    
    bouton.addEventListener("click", () => {
      if (!("geolocation" in navigator)) {
        statut.textContent = "La géolocalisation n'est pas prise en charge.";
        return;
      }
      statut.textContent = "Recherche en cours…";
      navigator.geolocation.getCurrentPosition(succes, echec, {
        enableHighAccuracy: true,
        timeout: 10000,
        maximumAge: 0,
      });
    });
    • On vérifie d'abord que l'API existe avec "geolocation" in navigator.
    • La demande est faite au clic et pas au chargement de la page : l'utilisateur comprend pourquoi on lui demande sa position, et accepte plus volontiers.
    • Les données sont insérées avec textContent (pas d'innerHTML).
    • Pour tester sans vous déplacer : DevTools (F12) → menu ⋮ → More tools → Sensors → Location: choisissez une ville ou saisissez des coordonnées (par exemple 36.8065, 10.1815 pour Tunis). Vous pouvez aussi simuler Location unavailable.
    1. Utiliser la géolocalisation avec async/await

      • L'API date d'avant les promesses : elle utilise des fonctions de rappel (callbacks). On l'« enveloppe » dans une promesse pour l'utiliser avec await, comme fetch (chapitre 19) :
      function obtenirPosition(options = {}) {
        return new Promise((resolve, reject) => {
          navigator.geolocation.getCurrentPosition(resolve, reject, options);
        });
      }
      
      async function afficherVille() {
        try {
          const { coords } = await obtenirPosition({ timeout: 8000 });
          console.log(`Vous êtes à ${coords.latitude.toFixed(2)}, ${coords.longitude.toFixed(2)}`);
        } catch (erreur) {
          console.error("Géolocalisation impossible :", erreur.message);
        }
      }
      • C'est la méthode utilisée dans le TP : on enchaîne naturellement await obtenirPosition() puis await fetch(...) vers une API météo.
    2. Suivre un déplacement : watchPosition()

      • watchPosition() prend les mêmes paramètres que getCurrentPosition(), mais appelle la fonction de succès à chaque changement de position. Elle renvoie un identifiant qu'on passe à clearWatch() pour arrêter.
      • Exemple : mesurer la distance parcourue pendant une marche, grâce à la formule de haversine qui calcule la distance entre deux points du globe :
      // Distance à vol d'oiseau entre deux points (formule de haversine), en mètres
      function distance(lat1, lon1, lat2, lon2) {
        const R = 6371000; // rayon moyen de la Terre
        const rad = (deg) => (deg * Math.PI) / 180;
        const dLat = rad(lat2 - lat1);
        const dLon = rad(lon2 - lon1);
        const a =
          Math.sin(dLat / 2) ** 2 + Math.cos(rad(lat1)) * Math.cos(rad(lat2)) * Math.sin(dLon / 2) ** 2;
        return 2 * R * Math.asin(Math.sqrt(a));
      }
      
      let precedente = null;
      let total = 0;
      
      const idSuivi = navigator.geolocation.watchPosition(
        ({ coords }) => {
          if (precedente) {
            total += distance(precedente.latitude, precedente.longitude, coords.latitude, coords.longitude);
          }
          precedente = coords;
          console.log(`Distance parcourue : ${Math.round(total)} m`);
        },
        (erreur) => console.error(erreur.message),
        { enableHighAccuracy: true }
      );
      
      // Arrêter le suivi (économise la batterie)
      document.getElementById("btn-stop").addEventListener("click", () => {
        navigator.geolocation.clearWatch(idSuivi);
      });
      • Pensez à toujours appeler clearWatch() quand le suivi n'est plus utile : le GPS consomme beaucoup d'énergie.
    3. Connaître l'état de la permission

      • L'API Permissions indique, sans rien demander, si l'utilisateur a déjà accepté, refusé ou pas encore répondu. Cela permet par exemple de cacher le bouton « Me localiser » quand l'accès est bloqué, et d'afficher directement la recherche par ville (code dans un module, à cause du await au niveau supérieur) :
      const etat = await navigator.permissions.query({ name: "geolocation" });
      console.log(etat.state); // "granted", "denied" ou "prompt"
      
      etat.addEventListener("change", () => {
        console.log("La permission est maintenant :", etat.state);
      });
      • Un refus est mémorisé par le navigateur : la page ne peut pas redemander. Seul l'utilisateur peut changer ce choix (icône à gauche de l'adresse → Autorisations du site).
    4. Nouveauté : l'élément HTML <geolocation>

      • Depuis Chrome 144 (janvier 2026), un élément HTML <geolocation> expérimente une autre approche : un bouton fourni par le navigateur, sur lequel l'utilisateur clique pour partager sa position. Le navigateur est ainsi sûr que la demande vient bien d'une action volontaire.
      • Il n'est pas encore disponible dans Firefox et Safari : dans vos projets, continuez d'utiliser navigator.geolocation, qui fonctionne partout.
    5. Vie privée et bonnes pratiques

      • La position est une donnée personnelle: en Tunisie (loi organique n° 2004-63) comme en Europe (RGPD), on ne la collecte que si elle est nécessaire, on explique pourquoi, et on ne la conserve pas sans raison.
      • Demandez la position au moment où elle sert, après un clic, jamais dès l'ouverture de la page.
      • Prévoyez toujours une solution de repli : saisie d'une ville, d'un code postal, ou choix sur une liste.
      • N'utilisez enableHighAccuracy: true que si la précision au mètre est vraiment utile (une météo n'en a pas besoin).
      • Arrondissez les coordonnées affichées ou envoyées à un service (2 décimales ≈ 1 km) quand une grande précision n'est pas nécessaire.
    6. Activités

    7. Activité 1 : « Où suis-je ? »

    • Dans un dépôt GitHub js-api-navigateur, créez le dossier geolocalisation et reproduisez l'exemple complet. Testez-le avec Live Server.
    • Avec l'onglet Sensors des DevTools, simulez successivement Tunis, Sfax et Paris, puis Location unavailable. Notez le message affiché à chaque fois.
    • Refusez l'autorisation, puis retrouvez dans le navigateur comment la réinitialiser.

    Activité 2 : distance au centre de formation

    • Le centre se trouve aux coordonnées 34.7406, 10.7603 (Sfax). Ajoutez à la page la distance à vol d'oiseau, en kilomètres, entre l'utilisateur et le centre, avec la fonction distance().
    • Simulez la position de Tunis (36.8065, 10.1815). Quelle distance obtenez-vous ?
    • Affichez « Vous êtes au centre » si la distance est inférieure à 200 m.

    Activité 3 : version async

    • Réécrivez geo.js avec la fonction obtenirPosition() et try / catch. Le bouton doit être désactivé pendant la recherche.

    Activité 4 : questions

    • Pourquoi la géolocalisation ne fonctionne-t-elle pas sur une page ouverte en http:// sur un serveur distant ?
    • Que signifie maximumAge: 60000?
    • Quelle différence y a-t-il entre getCurrentPosition() et watchPosition()?
    Corrigés. Activité 2 : environ 236 km entre Tunis et Sfax à vol d'oiseau (la route est plus longue). Activité 4 : la géolocalisation exige un contexte sécurisé (HTTPS, ou localhost en développement) ; maximumAge: 60000 accepte une position mémorisée datant de moins d'une minute, ce qui donne une réponse immédiate ; getCurrentPosition() donne la position une seule fois, watchPosition() la redonne à chaque déplacement jusqu'à clearWatch().
  • À retenir

    • navigator.geolocation.getCurrentPosition(succes, echec, options) donne coords.latitude, coords.longitude et coords.accuracy.
    • Trois erreurs à gérer : refus (1), indisponible (2), délai dépassé (3).
    • Contexte sécurisé obligatoire, demande après un clic, solution de repli prévue.
    • On l'enveloppe dans une promesse pour l'utiliser avec async/await; watchPosition() + clearWatch() pour suivre un déplacement.

    Sources : MDN Web Docs, web.dev, W3C, WHATWG, open-meteo.com.