Peta pelacakan adalah layar keterlibatan tertinggi di aplikasi pengiriman makanan atau rideshare apa pun. Ini adalah apa yang pelanggan lihat saat mereka menunggu. Menyelesaikannya dengan benar, gerakan mulus, ETA akurat, garis rute yang jelas, adalah perbedaan antara aplikasi yang terasa profesional dan aplikasi yang terasa tidak dapat diandalkan.
Tutorial ini membangun peta pelacakan yang menghadap pelanggan dari prinsip pertama: backend yang menyiarkan posisi GPS melalui WebSocket, frontend yang menerima dan memindahkan penanda pengemudi tanpa melompat, garis rute dari MapAtlas Routing API, dan tampilan ETA langsung. Implementasi lengkap berada di bawah 70 baris JavaScript sisi klien, dirancang untuk terintegrasi dengan backend apa pun yang dapat mengirim pesan WebSocket.
Arsitektur bekerja untuk pengiriman makanan, bahan makanan, rideshare, layanan lapangan, dan kasus penggunaan lainnya di mana kendaraan bergerak menuju tujuan tetap dan pelanggan menontonnya terjadi secara real-time.
Ringkasan Arsitektur
Sebelum menulis kode, membantu memahami alur data:
- Aplikasi pengemudi (mobile, perangkat keras GPS) mengirimkan lintang/bujur ke backend Anda setiap 3-5 detik.
- Backend (Node.js, Python, Go, pilihan Anda) mempertahankan posisi terakhir yang diketahui dan menyiarkannya melalui WebSocket ke semua pelanggan pesanan terhubung.
- Browser pelanggan menerima pesan WebSocket dan memindahkan penanda pada peta menggunakan animasi interpolasi.
- Routing API dipanggil sekali ketika pesanan dibuat untuk mengambil rute yang direncanakan. Polyline yang didekodekan ditampilkan sebagai lapisan garis.
- ETA dihitung ulang dengan membandingkan jarak yang tersisa dengan kecepatan rata-rata, atau dengan memanggil ulang Routing API dari posisi pengemudi saat ini.
Implementasi backend berada di luar ruang lingkup tutorial ini, tetapi server WebSocket apa pun yang mengirim pesan dalam format ini bekerja dengan kode frontend di bawah:
{
"type": "position_update",
"orderId": "order-8821",
"lat": 52.3741,
"lng": 4.8952,
"heading": 92,
"speed": 28,
"timestamp": 1738234521000
}
Langkah 1: Inisialisasi Peta
Atur peta di pusat asal pengiriman. Panggilan Routing API terjadi di Langkah 4, jadi untuk sekarang tinggal inisialisasi kanvas.
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);
Langkah 2: Penanda Pengemudi dengan Rotasi Judul
Buat penanda pengemudi secara terpisah sehingga Anda dapat memperbarui posisinya pada setiap ping GPS. Elemen HTML khusus memungkinkan Anda memutar ikon penanda untuk mencerminkan arah pengemudi, detail kecil yang membuat pelacakan terasa jauh lebih realistis.
// 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)`;
}
Langkah 3: Koneksi WebSocket dan Interpolasi Halus
Ini adalah inti peta pelacakan. Menghubungkan ke WebSocket adalah satu baris, bagian yang menarik adalah menginterpolasi posisi penanda antara ping GPS sehingga meluncur dengan mulus daripada teleportasi.
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.');
});
Jendela interpolasi 400ms cukup cocok dengan interval ping GPS khas 3-5 detik, penanda selalu sedikit di belakang kenyataan tetapi tidak pernah melompat terlihat.
Langkah 4: Tarik Rute Terencana dari Routing API
Ambil rute lengkap ketika pesanan ditugaskan. Simpan koordinat polyline dan gambarkan sebagai lapisan garis GeoJSON. Tutorial Route Optimization API mencakup skenario multi-stop, untuk pengiriman A-ke-B sederhana permintaannya mudah.
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
}
Langkah 5: Perhitungan dan Tampilan ETA
Hitung ETA dengan membandingkan posisi pengemudi saat ini dengan tujuan. Untuk akurasi tinggi, panggil ulang Routing API dari posisi pengemudi saat ini setiap 30 detik untuk mendapatkan perkiraan waktu perjalanan segar.
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`;
}
}
}
Pertimbangan GDPR untuk Pelacakan Pengemudi
Koordinat GPS pengemudi adalah data pribadi di bawah Pasal 4(1) GDPR. Peraturan yang mengatur platform pengiriman makanan dan rideshare UE pada titik ini tidak ambigu:
Meminimalkan data: Lacak hanya bidang yang Anda butuhkan untuk pengiriman, posisi, judul, kecepatan. Jangan catat riwayat GPS mentah di luar apa yang diperlukan secara operasional.
Batas retensi: Data pelacakan perjalanan granular harus dihapus atau dianonimkan secara irreversibel setelah pesanan selesai. Data rute yang diagregat (tanpa tautan kembali ke pengemudi individual) dapat dipertahankan lebih lama untuk optimasi jaringan.
Dasar hukum: Kepentingan sah di bawah Pasal 6(1)(f) mencakup pelacakan pengiriman real-time. Untuk penggunaan sekunder data pelacakan (analitik, benchmarking), Anda perlu mendokumentasikan dasar terpisah.
Transparansi pengemudi: Sertakan pengungkapan pelacakan yang jelas dalam orientasi pengemudi. Pengemudi harus diberitahu apa yang dikumpulkan, berapa lama itu dipertahankan, dan siapa yang dapat mengaksesnya.
Residensi data: MapAtlas memproses semua permintaan API dalam UE. Ini menghilangkan kekhawatiran transfer negara ketiga yang timbul dari penyedia pemetaan berbasis AS. Lihat Panduan Pengembang UE untuk API Peta Patuh GDPR untuk gambaran kepatuhan lengkap.
Untuk kasus penggunaan industri ridesharing dan mobilitas secara khusus, MapAtlas menyertakan dokumentasi DPA dan jaminan server UE sebagai standar. Halaman industri logistik dan pengiriman mencakup skenario armada dan multi-pengemudi.
Pengerasan Produksi
Sebelum mengirimkan fitur pelacakan kepada pelanggan, periksa item-item ini:
- Koneksi ulang WebSocket: Tambahkan
ws.addEventListener('close', reconnect)dengan backoff eksponensial. Jaringan mobile sering menjatuhkan koneksi. - Penanganan posisi basi: Jika tidak ada pembaruan tiba selama 15 detik, tampilkan status "menemukan pengemudi" daripada meninggalkan posisi terakhir terlihat.
- Deteksi kedatangan: Ketika
distKm < 0.1, picu status "tiba", tutup WebSocket, dan tampilkan layar konfirmasi. - Kamera mengikuti pengemudi: Panggil
map.panTo([lng, lat])pada setiap pembaruan posisi untuk menjaga pengemudi tetap terpusat. Beri pengguna toggle "kunci" untuk menonaktifkan mode ikuti jika mereka ingin menjelajahi peta.
Langkah Berikutnya
- Daftar untuk kunci API MapAtlas gratis Anda dan mulai membangun
- Baca tutorial Route Optimization API untuk menambahkan pengiriman multi-stop ke aplikasi pengiriman Anda
- Jelajahi tutorial Real Estate Property Map untuk contoh lain dari lapisan peta dinamis yang digerakkan data
Pertanyaan yang Sering Diajukan
Bagaimana cara saya menampilkan lokasi pengemudi bergerak mulus di peta?
Ping GPS tiba setiap beberapa detik, menciptakan lompatan yang terlihat jika Anda memperbarui posisi penanda secara langsung. Interpolasi halus menganimasikan penanda antara posisi sebelumnya dan yang baru selama durasi singkat (300-500ms), menggunakan requestAnimationFrame untuk memindahkan penanda dalam kenaikan kecil. Ini memberikan tampilan gerakan berkelanjutan bahkan dengan pembaruan GPS yang jarang.
Apakah data lokasi pengemudi tunduk pada GDPR?
Ya. Koordinat GPS real-time pengemudi adalah data pribadi di bawah Pasal 4 GDPR. Platform pengiriman makanan dan rideshare UE harus meminimalkan retensi, data pelacakan harus dihapus atau dianonimkan setelah perjalanan selesai. Pemrosesan memerlukan dasar hukum dan harus diungkapkan dalam pemberitahuan privasi pengemudi.
Bisakah saya menggunakan MapAtlas Routing API untuk menampilkan rute terencana di peta pelacakan?
Ya. Ambil rute dari Routing API ketika perjalanan dibuat, dekodekan polyline, dan tambahkan sebagai lapisan garis GeoJSON pada peta. Saat pengemudi bergerak, Anda dapat secara opsional mengambil ulang rute dari posisi saat ini untuk menghitung ulang ETA secara dinamis.
