À 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.
-
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.
-
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, lelocalStorage(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.1pendant 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.
- 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,
-
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()etclearWatch(). - 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…

-
Obtenir la position : getCurrentPosition()
navigator.geolocation.getCurrentPosition(succes, echec, options);
succes(position): fonction appelée quand la position est connue. L'objet reçu contientposition.coords(latitude,longitude,accuracyen mètres, et parfoisaltitude,speed,heading) etposition.timestamp.echec(erreur): fonction appelée en cas de problème.erreur.codevaut1(refus de l'utilisateur),2(position indisponible) ou3(délai dépassé).options(facultatif) :
| Option | Valeur par défaut | Rôle |
|---|---|---|
enableHighAccuracy | false | true demande la meilleure précision (GPS) : plus lent et consomme plus de batterie. |
timeout | Infinity | Temps maximal d'attente en millisecondes avant l'erreur 3. |
maximumAge | 0 | Â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.
-
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, commefetch(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()puisawait fetch(...)vers une API météo.
- L'API date d'avant les promesses : elle utilise des fonctions de rappel (callbacks). On l'« enveloppe » dans une promesse pour l'utiliser avec
-
Suivre un déplacement : watchPosition()
watchPosition()prend les mêmes paramètres quegetCurrentPosition(), 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.
-
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
awaitau 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).
- 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
-
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.
- Depuis Chrome 144 (janvier 2026), un élément HTML
-
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: trueque 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.
-
Activités
Activité 1 : « Où suis-je ? »
- Dans un dépôt GitHub
js-api-navigateur, créez le dossiergeolocalisationet 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.jsavec la fonctionobtenirPosition()ettry / 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()etwatchPosition()?
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)donnecoords.latitude,coords.longitudeetcoords.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.