Skip to main content
Live-Tracking-Karte für Fahrer in Liefer- und Ridesharing-Apps bauen
Tutorials

Live-Tracking-Karte für Fahrer in Liefer- und Ridesharing-Apps bauen

Bauen Sie eine Echtzeit-Tracking-Karte mit WebSocket-GPS-Updates, flüssiger Marker-Interpolation, Routenanzeige und ETA-Berechnung über die MapAtlas Maps und Routing API.

Brent van der Heiden9 min read
#live tracking map#driver tracking#real-time map#websocket map#delivery tracking#rideshare app

Die Tracking-Karte ist der Screen mit dem höchsten Engagement in jeder App für Essenslieferungen oder Ridesharing. Auf ihn schauen Kunden, während sie warten. Ob die Umsetzung gelingt, also flüssige Bewegung, genaue ETAs und eine klare Routenlinie, entscheidet darüber, ob eine App professionell oder unzuverlässig wirkt.

Dieses Tutorial baut die Tracking-Karte für Kunden von Grund auf: ein Backend, das GPS-Positionen per WebSocket verteilt, ein Frontend, das sie empfängt und einen Fahrermarker ohne Sprünge bewegt, eine Routenlinie aus der MapAtlas Routing API und eine Live-Anzeige der ETA. Die vollständige Implementierung umfasst weniger als 70 Zeilen clientseitiges JavaScript und lässt sich mit jedem Backend verbinden, das WebSocket-Nachrichten senden kann.

Die Architektur eignet sich für Essenslieferungen, Lebensmittellieferungen, Ridesharing, Außendienst und jeden anderen Anwendungsfall, bei dem sich ein Fahrzeug auf ein festes Ziel zubewegt und ein Kunde das in Echtzeit verfolgt.

Die Architektur im Überblick

Bevor Sie Code schreiben, lohnt ein Blick auf den Datenfluss:

  1. Die Fahrer-App (Smartphone, GPS-Hardware) sendet alle 3 bis 5 Sekunden Breiten- und Längengrad an Ihr Backend.
  2. Das Backend (Node.js, Python, Go, ganz nach Wahl) speichert die letzte bekannte Position und verteilt sie per WebSocket an alle verbundenen Abonnenten der Bestellung.
  3. Der Browser des Kunden empfängt die WebSocket-Nachrichten und bewegt einen Marker mit interpolierter Animation über die Karte.
  4. Die Routing API wird beim Anlegen der Bestellung einmal aufgerufen, um die geplante Route abzurufen. Die dekodierte Polyline wird als Linien-Layer angezeigt.
  5. Die ETA wird neu berechnet, indem die verbleibende Strecke mit der Durchschnittsgeschwindigkeit verrechnet wird, oder durch einen erneuten Aufruf der Routing API ab der aktuellen Position des Fahrers.

Die Implementierung des Backends gehört nicht zu diesem Tutorial. Jeder WebSocket-Server, der Nachrichten in diesem Format sendet, funktioniert aber mit dem folgenden Frontend-Code:

{
  "type": "position_update",
  "orderId": "order-8821",
  "lat": 52.3741,
  "lng": 4.8952,
  "heading": 92,
  "speed": 28,
  "timestamp": 1738234521000
}

Schritt 1: Karte initialisieren

Richten Sie die Karte mit dem Ausgangspunkt der Lieferung als Zentrum ein. Der Aufruf der Routing API folgt in Schritt 4, vorerst initialisieren Sie nur die Kartenfläche.

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

// Zielmarker (Restaurant oder Abholpunkt)
const destination = [4.9001, 52.3791];

new mapmetricsgl.Marker({ color: '#EF4444' })
  .setLngLat(destination)
  .setPopup(new mapmetricsgl.Popup().setHTML('<strong>Pickup point</strong>'))
  .addTo(map);

Schritt 2: Fahrermarker mit Drehung nach Fahrtrichtung

Legen Sie den Fahrermarker separat an, damit Sie seine Position bei jedem GPS-Ping aktualisieren können. Mit einem eigenen HTML-Element lässt sich das Markersymbol passend zur Fahrtrichtung drehen. Dieses kleine Detail lässt das Tracking deutlich realistischer wirken.

// Eigenes Element, damit es sich drehen lässt
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)`;
}

Schritt 3: WebSocket-Verbindung und flüssige Interpolation

Das ist der Kern der Tracking-Karte. Die Verbindung zum WebSocket ist eine einzige Zeile. Interessant wird es bei der Interpolation der Markerposition zwischen den GPS-Pings, damit der Marker gleitet, statt zu springen.

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) {
    // Flüssige Animation von der vorherigen zur neuen Position
    interpolateMarker(prevPos.lat, prevPos.lng, lat, lng, 400);
  } else {
    // Erster Ping, Marker sofort platzieren
    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.');
});

Das Interpolationsfenster von 400 ms passt ausreichend gut zu einem typischen GPS-Ping-Intervall von 3 bis 5 Sekunden. Der Marker liegt immer leicht hinter der tatsächlichen Position, springt aber nie sichtbar.

Schritt 4: Geplante Route aus der Routing API zeichnen

Rufen Sie die vollständige Route ab, sobald die Bestellung zugewiesen ist. Speichern Sie die Koordinaten der Polyline und zeichnen Sie sie als GeoJSON-Linien-Layer. Szenarien mit mehreren Stopps behandelt das Tutorial zur Route Optimization API. Für eine einfache Lieferung von A nach B ist die Anfrage unkompliziert.

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; // Sekunden
}

Schritt 5: ETA berechnen und anzeigen

Berechnen Sie die ETA, indem Sie die aktuelle Position des Fahrers mit dem Ziel vergleichen. Für eine hohe Genauigkeit rufen Sie die Routing API alle 30 Sekunden erneut ab der aktuellen Position des Fahrers auf und erhalten so eine frische Schätzung der Fahrzeit.

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);

  // Schnelle clientseitige Schätzung (angenommener Stadtdurchschnitt von 30 km/h)
  const minutesEstimate = Math.ceil((distKm / 30) * 60);
  document.getElementById('eta').textContent =
    distKm < 0.1
      ? 'Arriving now'
      : `ETA: ${minutesEstimate} min (${distKm.toFixed(1)} km)`;

  // Für mehr Genauigkeit alle 30 Sekunden neu von der Routing API abrufen
  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`;
    }
  }
}

DSGVO-Aspekte beim Fahrer-Tracking

Die GPS-Koordinaten eines Fahrers sind personenbezogene Daten nach Art. 4 Nr. 1 DSGVO. Hier gelten die DSGVO-Grundsätze der Datenminimierung und Speicherbegrenzung aus Art. 5:

Datenminimierung: Erfassen Sie nur die Felder, die Sie für die Disposition brauchen: Position, Fahrtrichtung, Geschwindigkeit. Speichern Sie keinen GPS-Rohverlauf über das betrieblich Notwendige hinaus.

Speicherbegrenzung: Detaillierte Tracking-Daten einer Fahrt sollten nach Abschluss der Bestellung gelöscht oder unumkehrbar anonymisiert werden. Aggregierte Routendaten ohne Rückbezug auf einzelne Fahrer können für die Netzoptimierung länger aufbewahrt werden.

Rechtsgrundlage: Das berechtigte Interesse nach Art. 6 Abs. 1 lit. f DSGVO, gestützt auf eine dokumentierte Interessenabwägung, oder die Vertragserfüllung nach Art. 6 Abs. 1 lit. b DSGVO deckt das Echtzeit-Tracking für die Disposition in der Regel ab. Für jede weitere Nutzung der Tracking-Daten (Analysen, Benchmarking) müssen Sie eine eigene Rechtsgrundlage dokumentieren.

Transparenz gegenüber Fahrern: Informieren Sie beim Onboarding klar über das Tracking. Fahrer müssen erfahren, welche Daten erfasst werden, wie lange sie gespeichert werden und wer darauf zugreifen kann.

Datenstandort: MapAtlas verarbeitet alle API-Anfragen innerhalb der EU. Damit entfällt die Frage der Übermittlung in Drittländer, die sich bei Kartenanbietern mit Sitz in den USA stellt. Das vollständige Bild zur Compliance bietet der Leitfaden für EU-Entwickler zu DSGVO-konformen Karten-APIs.

Speziell für Anwendungsfälle in der Ridesharing- und Mobilitätsbranche bietet MapAtlas standardmäßig Dokumentation zum Auftragsverarbeitungsvertrag und Garantien für EU-Server. Die Branchenseite zu Logistik und Lieferung behandelt Szenarien mit Flotten und mehreren Fahrern.

Absicherung für den Produktivbetrieb

Bevor Sie eine Tracking-Funktion für Kunden freigeben, prüfen Sie diese Punkte:

  • WebSocket-Reconnect: Ergänzen Sie ws.addEventListener('close', reconnect) mit exponentiellem Backoff. Mobilfunknetze brechen Verbindungen häufig ab.
  • Veraltete Positionen: Kommt 15 Sekunden lang kein Update, zeigen Sie einen Status wie „Fahrer wird geortet“, statt die letzte Position stehen zu lassen.
  • Ankunftserkennung: Bei distKm < 0.1 lösen Sie den Status „angekommen“ aus, schließen den WebSocket und zeigen eine Bestätigungsseite.
  • Kamera folgt dem Fahrer: Rufen Sie bei jedem Positionsupdate map.panTo([lng, lat]) auf, damit der Fahrer zentriert bleibt. Geben Sie Nutzern einen Schalter zum Fixieren, mit dem sie den Folgemodus abschalten können, wenn sie die Karte selbst erkunden möchten.

Nächste Schritte

Häufig gestellte Fragen

Wie bewege ich die Position eines Fahrers flüssig auf einer Karte?

GPS-Pings treffen alle paar Sekunden ein und erzeugen sichtbare Sprünge, wenn Sie die Markerposition direkt aktualisieren. Eine flüssige Interpolation animiert den Marker über eine kurze Dauer (300 bis 500 ms) zwischen der vorherigen und der neuen Position und bewegt ihn mit requestAnimationFrame in kleinen Schritten. So wirkt die Bewegung auch bei seltenen GPS-Updates kontinuierlich.

Unterliegen Standortdaten von Fahrern der DSGVO?

Ja. Die Echtzeit-GPS-Koordinaten eines Fahrers sind personenbezogene Daten nach Art. 4 DSGVO. Plattformen sollten Tracking-Daten nur so lange aufbewahren wie nötig, und am sichersten ist es, sie nach Abschluss der Fahrt standardmäßig zu löschen oder zu anonymisieren. Die Verarbeitung braucht eine Rechtsgrundlage und muss in der Datenschutzerklärung für Fahrer offengelegt werden.

Kann ich mit der MapAtlas Routing API die geplante Route auf der Tracking-Karte anzeigen?

Ja. Rufen Sie die Route beim Anlegen einer Fahrt über die Routing API ab, dekodieren Sie die Polyline und fügen Sie sie als GeoJSON-Linien-Layer zur Karte hinzu. Während der Fahrt können Sie die Route optional ab der aktuellen Position neu abrufen, um die ETA dynamisch neu zu berechnen.

Häufig gestellte Fragen

Wie bewege ich die Position eines Fahrers flüssig auf einer Karte?

GPS-Pings treffen alle paar Sekunden ein und erzeugen sichtbare Sprünge, wenn Sie die Markerposition direkt aktualisieren. Eine flüssige Interpolation animiert den Marker über eine kurze Dauer (300 bis 500 ms) zwischen der vorherigen und der neuen Position und bewegt ihn mit requestAnimationFrame in kleinen Schritten. So wirkt die Bewegung auch bei seltenen GPS-Updates kontinuierlich.

Unterliegen Standortdaten von Fahrern der DSGVO?

Ja. Die Echtzeit-GPS-Koordinaten eines Fahrers sind personenbezogene Daten nach Art. 4 DSGVO. Plattformen sollten Tracking-Daten nur so lange aufbewahren wie nötig, und am sichersten ist es, sie nach Abschluss der Fahrt standardmäßig zu löschen oder zu anonymisieren. Die Verarbeitung braucht eine Rechtsgrundlage (in der Regel berechtigtes Interesse für die Disposition oder die Vertragserfüllung) und muss in der Datenschutzerklärung für Fahrer offengelegt werden.

Kann ich mit der MapAtlas Routing API die geplante Route auf der Tracking-Karte anzeigen?

Ja. Rufen Sie die Route beim Anlegen einer Fahrt über die Routing API ab, dekodieren Sie die Polyline und fügen Sie sie als GeoJSON-Linien-Layer zur Karte hinzu. Während der Fahrt können Sie die Route optional ab der aktuellen Position neu abrufen, um die ETA dynamisch neu zu berechnen.

Hat Ihnen das geholfen? Teilen Sie es.

Über den Autor

Brent van der Heiden

Verfasst von

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.

Alle Artikel ansehen →
Zurück zum Blog