La carte de suivi est l'ecran le plus engageant de n'importe quelle application de livraison alimentaire ou de covoiturage. C'est ce que les clients regardent en attendant. Bien faire les choses, un mouvement en douceur, des ETAs precises, une ligne d'itineraire claire, c'est la difference entre une application qui semble professionnelle et une qui semble peu fiable.
Ce tutoriel construit la carte de suivi orientee vers le client a partir des principes premiers : un backend qui diffuse les positions GPS via WebSocket, un frontend qui les recoit et deplace un marqueur de chauffeur sans saut, une ligne d'itineraire a partir de l'API de routage MapAtlas, et un affichage en direct de l'ETA. L'implementation complete est inferieure a 70 lignes de JavaScript cote client, concue pour s'integrer a n'importe quel backend pouvant pousser des messages WebSocket.
L'architecture fonctionne pour la livraison alimentaire, les epiceries, le covoiturage, les services sur site et tout autre cas d'usage ou un vehicule se deplace vers une destination fixe et un client la regarde se produire en temps reel.
Apercu de l'architecture
Avant d'ecrire du code, il est utile de comprendre le flux de donnees :
- Application de chauffeur (materiel mobile, GPS) envoie la latitude/longitude a votre backend toutes les 3 a 5 secondes.
- Backend (Node.js, Python, Go, votre choix) persiste la derniere position connue et la diffuse via WebSocket a tous les abonnes de commande connectes.
- Le navigateur du client recoit les messages WebSocket et deplace un marqueur sur la carte en utilisant une animation interpolee.
- L'API de routage est appelee une fois lors de la creation de la commande pour recuperer l'itineraire planifie. La polyline decodee est affichee sous forme de couche de ligne.
- L'ETA est recalcule en comparant la distance restante a la vitesse moyenne, ou en re-appelant l'API de routage a partir de la position actuelle du chauffeur.
L'implementation du backend est en dehors de la portee de ce tutoriel, mais n'importe quel serveur WebSocket qui envoie des messages dans ce format fonctionne avec le code frontend ci-dessous :
{
"type": "position_update",
"orderId": "order-8821",
"lat": 52.3741,
"lng": 4.8952,
"heading": 92,
"speed": 28,
"timestamp": 1738234521000
}
Etape 1 : Initialisation de la carte
Configurez la carte centree sur l'origine de la livraison. L'appel de l'API de routage se produit a l'etape 4, alors pour l'instant, initialisez simplement le canevas.
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const map = new mapmetricsgl.Map({
container: 'tracking-map',
style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
center: [4.9041, 52.3676],
zoom: 14
});
// Destination marker (restaurant or pickup point)
const destination = [4.9001, 52.3791];
new mapmetricsgl.Marker({ color: '#EF4444' })
.setLngLat(destination)
.setPopup(new mapmetricsgl.Popup().setHTML('<strong>Pickup point</strong>'))
.addTo(map);
Etape 2 : Marqueur de chauffeur avec rotation de direction
Creez le marqueur de chauffeur separement afin de pouvoir mettre a jour sa position a chaque ping GPS. Un element HTML personnalise vous permet de faire pivoter l'icone du marqueur pour reflechir la direction du chauffeur, un petit detail qui rend le suivi beaucoup plus realiste.
// Custom element so we can rotate it
const driverEl = document.createElement('div');
driverEl.innerHTML = '🚗';
driverEl.style.cssText = 'font-size:28px;transform-origin:center;transition:transform 0.3s';
const driverMarker = new mapmetricsgl.Marker({ element: driverEl, anchor: 'center' })
.setLngLat([4.9041, 52.3676])
.addTo(map);
function setDriverHeading(heading) {
driverEl.style.transform = `rotate(${heading}deg)`;
}
Etape 3 : Connexion WebSocket et interpolation fluide
C'est le coeur de la carte de suivi. La connexion au WebSocket est une ligne, la partie interessante est l'interpolation de la position du marqueur entre les pings GPS pour qu'il glisse en douceur plutot que de se teleporter.
let prevPos = null; // { lat, lng }
let animFrame = null;
function interpolateMarker(fromLat, fromLng, toLat, toLng, durationMs) {
const startTime = performance.now();
function step(now) {
const elapsed = now - startTime;
const t = Math.min(elapsed / durationMs, 1); // 0 → 1
const lat = fromLat + (toLat - fromLat) * t;
const lng = fromLng + (toLng - fromLng) * t;
driverMarker.setLngLat([lng, lat]);
if (t < 1) {
animFrame = requestAnimationFrame(step);
}
}
if (animFrame) cancelAnimationFrame(animFrame);
animFrame = requestAnimationFrame(step);
}
const ws = new WebSocket('wss://your-backend.example.com/track/order-8821');
ws.addEventListener('message', (event) => {
const msg = JSON.parse(event.data);
if (msg.type !== 'position_update') return;
const { lat, lng, heading } = msg;
if (prevPos) {
// Smooth animation from previous to new position
interpolateMarker(prevPos.lat, prevPos.lng, lat, lng, 400);
} else {
// First ping, place marker immediately
driverMarker.setLngLat([lng, lat]);
map.flyTo({ center: [lng, lat], zoom: 15 });
}
setDriverHeading(heading);
updateETA(lat, lng);
prevPos = { lat, lng };
});
ws.addEventListener('close', () => {
console.log('Driver has arrived or connection closed.');
});
La fenetre d'interpolation de 400 ms correspond raisonnablement bien a un intervalle de ping GPS typique de 3 a 5 secondes, le marqueur est toujours legerement en retard sur la realite mais ne saute jamais de maniere appreciable.
Etape 4 : Dessinez l'itineraire planifie a partir de l'API de routage
Recuperez l'itineraire complet lors de l'attribution de la commande. Stockez les coordonnees de la polyline et dessinez-les en tant que couche de ligne GeoJSON. Le tutoriel de l'API de routage couvre les scenarios multi-arrets, pour une simple livraison A-B, la demande est directe.
async function fetchAndDrawRoute(originLat, originLng, destLat, destLng) {
const url = new URL('https://api.mapatlas.eu/v1/routing/route');
url.searchParams.set('origin', `${originLat},${originLng}`);
url.searchParams.set('destination', `${destLat},${destLng}`);
url.searchParams.set('profile', 'driving');
url.searchParams.set('key', 'YOUR_API_KEY');
const res = await fetch(url);
const data = await res.json();
if (!data.routes?.length) return;
const route = data.routes[0];
map.on('load', () => {
map.addSource('route', {
type: 'geojson',
data: {
type: 'Feature',
geometry: route.geometry // GeoJSON LineString
}
});
map.addLayer({
id: 'route-line',
type: 'line',
source: 'route',
layout: { 'line-join': 'round', 'line-cap': 'round' },
paint: {
'line-color': '#3B82F6',
'line-width': 4,
'line-opacity': 0.8
}
});
});
return route.duration; // seconds
}
Etape 5 : Calcul et affichage de l'ETA
Calculez l'ETA en comparant la position actuelle du chauffeur a la destination. Pour une precision elevee, re-appelez l'API de routage a partir de la position actuelle du chauffeur toutes les 30 secondes pour obtenir une estimation de temps de deplacement fraiche.
function haversineKm(lat1, lon1, lat2, lon2) {
const R = 6371;
const dLat = ((lat2 - lat1) * Math.PI) / 180;
const dLon = ((lon2 - lon1) * Math.PI) / 180;
const a = Math.sin(dLat / 2) ** 2 +
Math.cos((lat1 * Math.PI) / 180) *
Math.cos((lat2 * Math.PI) / 180) *
Math.sin(dLon / 2) ** 2;
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
let lastRouteFetch = 0;
async function updateETA(driverLat, driverLng) {
const [destLng, destLat] = destination;
const distKm = haversineKm(driverLat, driverLng, destLat, destLng);
// Fast client-side estimate (assume 30 km/h urban average)
const minutesEstimate = Math.ceil((distKm / 30) * 60);
document.getElementById('eta').textContent =
distKm < 0.1
? 'Arriving now'
: `ETA: ${minutesEstimate} min (${distKm.toFixed(1)} km)`;
// Re-fetch from Routing API every 30 seconds for accuracy
const now = Date.now();
if (now - lastRouteFetch > 30_000) {
lastRouteFetch = now;
const url = new URL('https://api.mapatlas.eu/v1/routing/route');
url.searchParams.set('origin', `${driverLat},${driverLng}`);
url.searchParams.set('destination', `${destLat},${destLng}`);
url.searchParams.set('profile', 'driving');
url.searchParams.set('key', 'YOUR_API_KEY');
const res = await fetch(url);
const data = await res.json();
if (data.routes?.length) {
const mins = Math.ceil(data.routes[0].duration / 60);
document.getElementById('eta').textContent = `ETA: ${mins} min`;
}
}
}
Considerations RGPD pour le suivi des chauffeurs
Les coordonnees GPS des chauffeurs sont des donnees personnelles en vertu de l'article 4(1) du RGPD. Les reglementations qui regissent les plates-formes de livraison alimentaire et de covoiturage de l'UE sur ce point ne sont pas ambigues :
Minimisation des donnees : Suivez uniquement les champs dont vous avez besoin pour l'expedition, la position, la direction, la vitesse. Ne journalisez pas l'historique GPS brut au-dela de ce qui est operationnellement necessaire.
Limites de retention : Les donnees granulaires de suivi de trajets doivent etre supprimees ou rendues irrevocablement anonymes une fois la commande terminnee. Les donnees d'itineraire agreges (sans lien avec un chauffeur individuel) peuvent etre conservees plus longtemps pour l'optimisation du reseau.
Base juridique : L'interet legitime en vertu de l'article 6(1)(f) couvre le suivi du routage en temps reel. Pour tout usage secondaire des donnees de suivi (analyses, benchmarking), vous devez documenter une base distincte.
Transparence du chauffeur : Incluez une divulgation de suivi claire lors de l'integration des chauffeurs. Les chauffeurs doivent etre informes de ce qui est collecte, combien de temps c'est conserve et qui peut y acceder.
Residentialite des donnees : MapAtlas traite toutes les demandes d'API dans l'UE. Cela elimine la preoccupation de transfert vers un tiers pays qui survient avec les fournisseurs de cartographie bases aux Etats-Unis. Consultez le Guide du developpeur de l'UE pour les API cartographiques conformes au RGPD pour l'image de conformite complete.
Pour le cas d'usage specifique de l'industrie du covoiturage et de la mobilite, MapAtlas inclut la documentation DPA et les garanties de serveurs de l'UE comme norme. La page de l'industrie logistique et livraison couvre les scenarios de flotte et multi-chauffeurs.
Durcissement de la production
Avant d'envoyer une fonction de suivi aux clients, verifiez ces elements :
- Reconnexion WebSocket : Ajoutez
ws.addEventListener('close', reconnect)avec backoff exponentiel. Les reseaux mobiles eliminent les connexions frequemment. - Gestion des positions obsoletes : Si aucune mise a jour n'arrive pendant 15 secondes, affichez un etat « localisation du chauffeur » plutot que de laisser la derniere position visible.
- Detection d'arrivee : Quand
distKm < 0.1, declenchez un etat « arrive », fermez le WebSocket et affichez un ecran de confirmation. - La camera suit le chauffeur : Appelez
map.panTo([lng, lat])a chaque mise a jour de position pour garder le chauffeur centre. Donnez aux utilisateurs un bouton de basculement « verrou » pour desactiver le mode suivi s'ils souhaitent explorer la carte.
Prochaines etapes
- Inscrivez-vous pour votre cle d'API MapAtlas gratuite et commencez a construire
- Lisez le tutoriel de l'API de routage pour ajouter la expedition multi-arrets a votre application de livraison
- Explorez le tutoriel de carte immobiliere pour un autre exemple de couches cartographiques dynamiques et pilottes par les donnees
Questions frequemment posees
Comment afficher le deplacement en douceur de la localisation d'un chauffeur sur une carte ?
Les pings GPS arrivent toutes les quelques secondes, creant des sauts visibles si vous mettez a jour directement la position du marqueur. L'interpolation en douceur anime le marqueur entre la position anterieure et la nouvelle sur une courte duree (300 a 500 ms), en utilisant requestAnimationFrame pour deplacer le marqueur par petits increments. Cela donne l'apparence d'un mouvement continu meme avec des mises a jour GPS peu frequentes.
Les donnees de localisation des chauffeurs sont-elles soumises au RGPD ?
Oui. Les coordonnees GPS en temps reel d'un chauffeur sont des donnees personnelles en vertu de l'article 4 du RGPD. Les plates-formes de livraison alimentaire et de covoiturage de l'UE doivent minimiser la retention, les donnees de suivi doivent etre supprimees ou anonymisees une fois le trajet termine. Le traitement necessite une base juridique et doit etre divulgue dans l'avis de confidentialite du chauffeur.
Puis-je utiliser l'API de routage MapAtlas pour afficher l'itineraire planifie sur la carte de suivi ?
Oui. Recuperez l'itineraire a partir de l'API de routage lors de la creation d'un trajet, decodez la polyline et ajoutez-la en tant que couche de ligne GeoJSON sur la carte. Alors que le chauffeur se deplace, vous pouvez eventuellement re-recuperer l'itineraire a partir de la position actuelle pour recalculer l'ETA dynamiquement.
