Skip to main content
Tutorials

Comment créer une carte de suivi en direct des chauffeurs

Créez une carte de suivi des chauffeurs en temps réel : mises à jour GPS via WebSocket, interpolation fluide des marqueurs, itinéraire et ETA avec les API MapAtlas.

Brent van der Heiden10 min read
#live tracking map#driver tracking#real-time map#websocket map#delivery tracking#rideshare app
Comment créer une carte de suivi en direct des chauffeurs

La carte de suivi est l'écran le plus consulté de toute application de livraison de repas ou de VTC. C'est lui que les clients fixent pendant qu'ils attendent. Un déplacement fluide, une heure d'arrivée estimée (ETA) précise et un tracé d'itinéraire clair font la différence entre une application qui paraît professionnelle et une application qui paraît peu fiable.

Ce tutoriel construit la carte de suivi côté client en partant des bases : un backend qui diffuse les positions GPS via WebSocket, un frontend qui les reçoit et déplace le marqueur du chauffeur sans à-coups, un tracé d'itinéraire issu de la Routing API de MapAtlas et un affichage de l'ETA en direct. L'implémentation complète tient en moins de 70 lignes de JavaScript côté client et s'intègre à n'importe quel backend capable d'envoyer des messages WebSocket.

Cette architecture convient à la livraison de repas, aux courses alimentaires, au VTC, aux interventions sur site et à tout autre cas où un véhicule se dirige vers une destination fixe pendant qu'un client suit son trajet en temps réel.

Vue d'ensemble de l'architecture

Avant d'écrire du code, il est utile de comprendre le flux de données :

  1. L'application chauffeur (mobile, boîtier GPS) envoie la latitude et la longitude à votre backend toutes les 3 à 5 secondes.
  2. Le backend (Node.js, Python, Go, selon votre choix) enregistre la dernière position connue et la diffuse via WebSocket à tous les clients abonnés à la commande.
  3. Le navigateur du client reçoit les messages WebSocket et déplace un marqueur sur la carte grâce à une animation interpolée.
  4. La Routing API est appelée une seule fois, à la création de la commande, pour récupérer l'itinéraire prévu. La polyline décodée s'affiche sous forme de couche de ligne.
  5. L'ETA est recalculée en comparant la distance restante à une vitesse moyenne, ou en rappelant la Routing API depuis la position actuelle du chauffeur.

L'implémentation du backend dépasse le cadre de ce tutoriel, mais tout 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
}

Étape 1 : initialiser la carte

Configurez la carte en la centrant sur le point de départ de la livraison. L'appel à la Routing API intervient à l'étape 4 : 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://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/style.json&token=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);

Étape 2 : un marqueur chauffeur orienté selon le cap

Créez le marqueur du chauffeur séparément, pour pouvoir mettre à jour sa position à chaque ping GPS. Un élément HTML personnalisé permet de faire pivoter l'icône selon le cap du chauffeur. C'est un petit détail, mais il rend le suivi nettement plus réaliste.

// 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)`;
}

Étape 3 : connexion WebSocket et interpolation fluide

C'est le cœur de la carte de suivi. La connexion au WebSocket tient en une ligne. La partie intéressante consiste à interpoler la position du marqueur entre deux pings GPS, pour qu'il glisse de façon fluide au lieu de se téléporter.

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.');
});

Une fenêtre d'interpolation de 400 ms s'accorde assez bien avec un intervalle de ping GPS classique de 3 à 5 secondes : le marqueur a toujours un léger retard sur la réalité, mais ne fait jamais de saut visible.

Étape 4 : tracer l'itinéraire prévu avec la Routing API

Récupérez l'itinéraire complet au moment où la commande est attribuée. Stockez les coordonnées de la polyline et tracez-les sous forme de couche de ligne GeoJSON. Le tutoriel sur la Route Optimization API couvre les scénarios à arrêts multiples. Pour une livraison simple d'un point A à un point B, la requête est directe.

async function fetchAndDrawRoute(originLat, originLng, destLat, destLng) {
  const url = new URL('https://gateway.mapmetrics-atlas.net/directions/');
  url.searchParams.set('token', 'YOUR_API_KEY');

  const res  = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      locations: [
        { lat: originLat, lon: originLng },
        { lat: destLat, lon: destLng },
      ],
      costing: 'auto',
      format: 'osrm',
      shape_format: 'geojson',
    }),
  });
  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
}

Étape 5 : calculer et afficher l'ETA

Calculez l'ETA en comparant la position actuelle du chauffeur à la destination. Pour plus de précision, rappelez la Routing API depuis la position actuelle du chauffeur toutes les 30 secondes afin d'obtenir une estimation à jour du temps de trajet.

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://gateway.mapmetrics-atlas.net/directions/');
    url.searchParams.set('token', 'YOUR_API_KEY');

    const res  = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        locations: [
          { lat: driverLat, lon: driverLng },
          { lat: destLat, lon: destLng },
        ],
        costing: 'auto',
        format: 'osrm',
        shape_format: 'geojson',
      }),
    });
    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`;
    }
  }
}

Suivi des chauffeurs : ce qu'impose le RGPD

Les coordonnées GPS d'un chauffeur sont des données personnelles au sens de l'article 4, paragraphe 1, du RGPD. Les principes du RGPD qui s'appliquent ici sont la minimisation des données et la limitation de la conservation, prévues à l'article 5 :

Minimisation des données : ne collectez que les champs nécessaires à la répartition des courses, à savoir la position, le cap et la vitesse. Ne conservez pas d'historique GPS brut au-delà de ce qu'exige l'exploitation.

Durée de conservation : les données de suivi détaillées d'une course doivent être supprimées ou anonymisées de manière irréversible une fois la commande terminée. Les données d'itinéraire agrégées, sans lien avec un chauffeur identifiable, peuvent être conservées plus longtemps pour optimiser le réseau.

Base juridique : l'intérêt légitime prévu à l'article 6, paragraphe 1, point f, appuyé par une mise en balance documentée, ou l'exécution du contrat prévue au point b du même paragraphe couvre généralement le suivi en temps réel pour la répartition des courses. Pour toute utilisation secondaire des données de suivi (analyses, benchmarks), vous devez documenter une base juridique distincte.

Transparence envers les chauffeurs : informez clairement les chauffeurs du suivi dès leur intégration. Ils doivent savoir quelles données sont collectées, combien de temps elles sont conservées et qui peut y accéder.

Localisation des données : MapAtlas traite toutes les requêtes API au sein de l'UE. La question des transferts vers des pays tiers, qui se pose avec les fournisseurs cartographiques basés aux États-Unis, disparaît donc. Le guide du développeur européen sur les API cartographiques conformes au RGPD présente l'ensemble des exigences de conformité.

Pour le secteur du VTC et de la mobilité en particulier, MapAtlas fournit en standard la documentation de l'accord de traitement des données (DPA) et la garantie de serveurs situés dans l'UE. La page consacrée au secteur logistique et livraison couvre les scénarios de flotte et à plusieurs chauffeurs.

Préparer la mise en production

Avant de proposer une fonction de suivi à vos clients, vérifiez les points suivants :

  • Reconnexion WebSocket : ajoutez ws.addEventListener('close', reconnect) avec un backoff exponentiel. Les réseaux mobiles coupent souvent les connexions.
  • Positions périmées : si aucune mise à jour n'arrive pendant 15 secondes, affichez un état « localisation du chauffeur en cours » plutôt que de laisser la dernière position à l'écran.
  • Détection de l'arrivée : quand distKm < 0.1, déclenchez un état « arrivé », fermez le WebSocket et affichez un écran de confirmation.
  • Caméra qui suit le chauffeur : appelez map.panTo([lng, lat]) à chaque mise à jour de position pour garder le chauffeur au centre. Proposez un bouton de verrouillage qui désactive ce suivi si l'utilisateur veut explorer la carte.

Prochaines étapes

Questions fréquentes

Comment afficher le déplacement fluide d'un chauffeur sur une carte ?

Les pings GPS arrivent toutes les quelques secondes, ce qui crée des sauts visibles si vous mettez à jour la position du marqueur directement. L'interpolation fluide anime le marqueur entre l'ancienne et la nouvelle position sur une courte durée (300 à 500 ms), en utilisant requestAnimationFrame pour le déplacer par petits incréments. Le mouvement paraît ainsi continu, même avec des mises à jour GPS peu fréquentes.

Les données de localisation des chauffeurs sont-elles soumises au RGPD ?

Oui. Les coordonnées GPS en temps réel d'un chauffeur sont des données personnelles au sens de l'article 4 du RGPD. Les plateformes ne devraient conserver les données de suivi que le temps nécessaire, et les supprimer ou les anonymiser une fois la course terminée reste l'option par défaut la plus sûre. Le traitement exige une base juridique et doit figurer dans la notice de confidentialité remise au chauffeur.

Puis-je utiliser la Routing API MapAtlas pour afficher l'itinéraire prévu sur la carte de suivi ?

Oui. Récupérez l'itinéraire auprès de la Routing API à la création de la course, décodez la polyline et ajoutez-la à la carte comme couche de ligne GeoJSON. Pendant que le chauffeur avance, vous pouvez redemander l'itinéraire depuis sa position actuelle pour recalculer l'ETA dynamiquement.

Questions fréquemment posées

Comment afficher le déplacement fluide d'un chauffeur sur une carte ?

Les pings GPS arrivent toutes les quelques secondes, ce qui crée des sauts visibles si vous mettez à jour la position du marqueur directement. L'interpolation fluide anime le marqueur entre l'ancienne et la nouvelle position sur une courte durée (300 à 500 ms), en utilisant requestAnimationFrame pour le déplacer par petits incréments. Le mouvement paraît ainsi continu, même avec des mises à jour GPS peu fréquentes.

Les données de localisation des chauffeurs sont-elles soumises au RGPD ?

Oui. Les coordonnées GPS en temps réel d'un chauffeur sont des données personnelles au sens de l'article 4 du RGPD. Les plateformes ne devraient conserver les données de suivi que le temps nécessaire, et les supprimer ou les anonymiser une fois la course terminée reste l'option par défaut la plus sûre. Le traitement exige une base juridique (en général l'intérêt légitime pour la répartition des courses ou l'exécution du contrat) et doit figurer dans la notice de confidentialité remise au chauffeur.

Puis-je utiliser la Routing API MapAtlas pour afficher l'itinéraire prévu sur la carte de suivi ?

Oui. Récupérez l'itinéraire auprès de la Routing API à la création de la course, décodez la polyline et ajoutez-la à la carte comme couche de ligne GeoJSON. Pendant que le chauffeur avance, vous pouvez redemander l'itinéraire depuis sa position actuelle pour recalculer l'ETA dynamiquement.

Vous avez trouvé cela utile ? Partagez-le.

À propos de l'auteur

Brent van der Heiden

Rédigé par

Brent van der Heiden

Co-Founder & CEO at MapAtlas

Brent built MapAtlas out of a conviction that developers deserve location APIs with fair pricing and genuine end-user privacy. Before that he co-founded MapMetrics, a community mapping and navigation app. He writes about geospatial infrastructure, map data, AI search visibility, and how location data powers the products people rely on every day.

Voir tous les articles →
Retour au blog