Pernahkah kamu membuka Google Maps dan berpikir, "Gimana sih caranya bikin peta kayak gini di website saya?" Dulu saya juga begitu. Sampai akhirnya saya coba Mapbox GL JS, dan langsung jatuh cinta karena rendering-nya super smooth, support 3D, dan yang paling penting-gratis untuk pemakaian sampai 50.000 request per bulan.
Kalau kamu udah pernah pakai Leaflet.js (saya juga peral bahas sebelumnya), Mapbox GL JS itu level di atasnya. Leaflet render peta pakai tile image yang ditumpuk-tumpuk, sementara Mapbox GL JS pakai WebGL untuk render vektor secara real-time. Hasilnya? Peta yang bisa di-zoom tanpa pecah, tilt 3D, rotation, dan animasi transisi yang enak banget dilihat.
Apa Itu Mapbox GL JS?
Mapbox GL JS adalah library JavaScript untuk membuat peta interaktif berbasis WebGL. "GL" di sini singkatan dari Graphics Library, yang merujuk ke WebGL API di browser. Artinya, semua rendering peta dilakukan di GPU, bukan CPU. Ini bikin performanya jauh lebih baik dibanding library berbasis canvas atau DOM.
Beberapa fitur utama yang membedakan Mapbox GL JS dari library peta lain:
- Vector tiles: Data peta dikirim sebagai vektor, bukan raster image. Zoom seberapa pun tetap tajam, tidak pecah.
- 3D terrain & buildings: Bisa menampilkan elevasi terrain dan bangunan 3D langsung di browser.
- Custom styling: Kamu bisa custom warna, font, dan label peta sesuai brand. Mapbox punya editor visual (Mapbox Studio) yang intuitif banget.
- Smooth animations: Pan, zoom, dan rotate peta dengan animasi 60fps. Transisi antar style juga mulus.
- Geocoding & routing: API tambahan untuk konversi alamat ke koordinat (geocoding) dan kalkulasi rute (directions).
Setup Project: Dapatkan Mapbox Access Token
Pertama, kamu perlu daftar akun di mapbox.com. Setelah login, kamu akan dapet access token. Token ini wajib untuk load map tiles dan API Mapbox lainnya. Simpan token ini baik-baik-untuk production, sebaiknya pakai environment variable atau backend proxy supaya tidak exposed di client-side code.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Peta Interaktif dengan Mapbox GL JS</title>
<!-- Load Mapbox GL CSS -->
<link href="https://api.mapbox.com/mapbox-gl-js/v3.5.0/mapbox-gl.css"
rel="stylesheet">
<style>
body { margin: 0; padding: 0; }
#map { height: 100vh; width: 100vw; }
</style>
</head>
<body>
<div id="map"></div>
<!-- Load Mapbox GL JS -->
<script src="https://api.mapbox.com/mapbox-gl-js/v3.5.0/mapbox-gl.js"></script>
<script>
// Set access token kamu di sini
mapboxgl.accessToken = 'pk.eyJ1IjoieW91ci11c2VyIiwiYSI6...';
// Inisialisasi peta
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [106.8456, -6.2088], // Jakarta [lng, lat]
zoom: 12
});
// Tambahkan navigation control (zoom buttons + compass)
map.addControl(new mapboxgl.NavigationControl());
</script>
</body>
</html>
Coba buka file HTML ini di browser. Kamu akan lihat peta Jakarta dengan zoom buttons di pojok kanan atas. Cuma butuh sekitar 15 baris kode JavaScript. Bandingkan dengan setup Leaflet yang butuh tile layer configuration manual-Mapbox lebih straightforward.
Menambahkan Marker dan Popup
Peta tanpa marker itu seperti peta tanpa tujuan. Mari kita tambahkan beberapa marker dengan popup info. Ini use case paling umum untuk WebGIS: menampilkan lokasi-lokasi penting dengan detailnya.
// Data lokasi (bisa dari API backend kamu)
const locations = [
{
name: 'Monas',
description: 'Monumen Nasional, simbol kota Jakarta',
coords: [106.8272, -6.1754]
},
{
name: 'Kota Tua',
description: 'Area bersejarah dengan arsitektur kolonial Belanda',
coords: [106.8126, -6.1375]
},
{
name: 'Ancol',
description: 'Taman rekreasi tepi pantai di Jakarta Utara',
coords: [106.8431, -6.1263]
}
];
// Tunggu peta selesai loading
map.on('load', () => {
locations.forEach(loc => {
// Buat marker element custom
const el = document.createElement('div');
el.className = 'custom-marker';
el.style.width = '24px';
el.style.height = '24px';
el.style.backgroundColor = '#e74c3c';
el.style.borderRadius = '50%';
el.style.border = '3px solid #fff';
el.style.cursor = 'pointer';
// Buat marker
const marker = new mapboxgl.Marker(el)
.setLngLat(loc.coords)
.addTo(map);
// Buat popup
const popup = new mapboxgl.Popup({ offset: 25 })
.setHTML(`
<h3 style="margin:0 0 5px;font-size:16px;">${loc.name}</h3>
<p style="margin:0;font-size:13px;color:#555;">${loc.description}</p>
`);
marker.setPopup(popup);
});
});
Perhatikan bahwa koordinat di Mapbox pakai format [longitude, latitude], bukan [latitude, longitude] seperti yang biasa kita lihat di Google Maps. Ini sering jadi sumber bug untuk pemula-aku sendiri pernah debugging 2 jam cuma karena balik posisi lng dan lat.
Custom Style dengan Mapbox Studio
Salah satu alasan utama saya pilih Mapbox dibanding Google Maps API adalah fleksibilitas styling. Dengan Mapbox Studio, kamu bisa custom setiap elemen peta: warna jalan, ukuran label, ketinggian bangunan 3D, sampai warna laut. Semua via UI drag-and-drop, tanpa coding.
Cara kerjanya: kamu bikin custom style di Mapbox Studio, lalu publish. Setelah publish, kamu dapet style URL kayak mapbox://styles/your-username/clxxxxxxx. Ganti style URL di kode JavaScript kamu dengan style URL ini:
const map = new mapboxgl.Map({
container: 'map',
// Ganti dengan custom style URL kamu
style: 'mapbox://styles/your-username/clxxxxxxxxx',
center: [106.8456, -6.2088],
zoom: 12
});
Beberapa style preset gratis yang tersedia dan bisa langsung dipakai:
- streets-v12: Style peta jalan standar, cocok untuk navigasi.
- satellite-v9: Citra satelit, bagus untuk overlay data GIS.
- dark-v11: Dark mode, cocok untuk dashboard atau aplikasi monitoring malam hari.
- light-v11: Minimalis, cocok kalau kamu mau data layer jadi fokus utama.
- navigation-night-v1: Style navigasi dengan kontras tinggi untuk kondisi gelap.
Menampilkan Data GeoJSON di Peta
GeoJSON adalah format standar untuk data geospatial di web. Hampir semua WebGIS app akan handle GeoJSON di satu titik. Mari kita load data GeoJSON dan tampilkan sebagai layer di Mapbox.
map.on('load', () => {
// Load GeoJSON dari file atau API
map.addSource('jakarta-districts', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
name: 'Jakarta Pusat',
population: 913000
},
geometry: {
type: 'Polygon',
coordinates: [[[106.76, -6.10], [106.90, -6.10],
[106.90, -6.25], [106.76, -6.25],
[106.76, -6.10]]]
}
}
]
}
});
// Style polygon fill berdasarkan populasi
map.addLayer({
id: 'district-fill',
type: 'fill',
source: 'jakarta-districts',
paint: {
'fill-color': [
'interpolate',
['linear'],
['get', 'population'],
0, '#2ecc71', // hijau untuk populasi rendah
500000, '#f39c12', // oranye untuk menengah
1000000, '#e74c3c' // merah untuk tinggi
],
'fill-opacity': 0.6
}
});
// Tambahkan outline
map.addLayer({
id: 'district-outline',
type: 'line',
source: 'jakarta-districts',
paint: {
'line-color': '#2c3e50',
'line-width': 2
}
});
// Hover effect: ubah cursor saat di atas polygon
map.on('mouseenter', 'district-fill', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'district-fill', () => {
map.getCanvas().style.cursor = '';
});
// Click untuk lihat info
map.on('click', 'district-fill', (e) => {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(`
<h3>${e.features[0].properties.name}</h3>
<p>Populasi: ${e.features[0].properties.population.toLocaleString()}</p>
`)
.addTo(map);
});
});
Bagian interpolate di paint property itu powerful banget. Kamu bisa bikin choropleth map (peta tematik berdasarkan warna) tanpa library tambahan. Mapbox handle data-driven styling secara native. Di Leaflet, kamu harus manual loop dan set style per feature.
3D Terrain dan Buildings
Ini fitur yang bikin Mapbox GL JS benar-benar beda dari kompetitornya. Dengan satu baris konfigurasi, kamu bisa aktifkan terrain 3D berdasarkan data DEM (Digital Elevation Model) dari Mapbox.
map.on('load', () => {
// Aktifkan terrain 3D
map.addSource('mapbox-dem', {
type: 'raster-dem',
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
tileSize: 512,
maxzoom: 14
});
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });
// Tambahkan bangunan 3D (butuh style yang punya layer building)
map.addLayer({
id: '3d-buildings',
source: 'composite',
'source-layer': 'building',
filter: ['==', 'extrude', 'true'],
type: 'fill-extrusion',
minzoom: 15,
paint: {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': [
'interpolate', ['linear'],
['get', 'height'],
0, 0,
100, 100
],
'fill-extrusion-base': [
'interpolate', ['linear'],
['get', 'min_height'],
0, 0,
100, 100
],
'fill-extrusion-opacity': 0.8
}
});
// Tilt peta untuk efek 3D
map.setPitch(60); // 0 = top-down, 60 = miring
map.setBearing(-20); // rotasi dalam derajat
});
Saat aku pertama kali coba ini, langsung Mikir "ini bisa dibuat untuk visualisasi banjir atau tata kota." Bayangin aplikasi WebGIS yang bisa nunjukkin area rawan banjir dalam mode 3D-stakeholder langsung paham karena lebih intuitif daripada peta datar 2D.
Mapbox vs Leaflet vs Google Maps: Kapan Pakai Apa?
Berdasarkan pengalaman saya develop WebGIS di beberapa project, ini rangkuman kapan pakai mana:
- Leaflet.js: Cocok untuk project sederhana yang cuma butuh marker + popup + tile layer standar. Bundle size kecil (~40KB), tidak butuh API key untuk OSM tiles. Tapi tidak support 3D dan rendering vektor terbatas.
- Mapbox GL JS: Pilihan terbaik untuk WebGIS modern. Support 3D, custom styling, data-driven visualization, dan performa WebGL. Gratis sampai 50K loads/bulan. Tapi bundle size lebih besar (~500KB) dan butuh registrasi.
- Google Maps JavaScript API: Paling familiar untuk user, data tempat (POI) paling lengkap. Tapi berbayar setelah $200 credit/bulan (sekitar 28K loads), dan custom styling terbatas dibanding Mapbox.
Untuk project WebGIS internal atau dashboard, saya selalu pilih Mapbox. Untuk embed peta sederhana di blog atau landing page, Leaflet cukup. Google Maps cuma kalau client explicitly request atau butuh integrasi Google Places API.
Optimasi Performa untuk Production
Beberapa tips yang saya pelajari dari project production:
1. Clustering untuk marker banyak: Kalau kamu punya 1000+ marker, jangan render semua sekaligus. Pakai Mapbox clustering:
map.addSource('locations', {
type: 'geojson',
data: geojsonData,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'locations',
filter: ['has', 'point_count'],
paint: {
'circle-color': '#3498db',
'circle-radius': [
'step', ['get', 'point_count'],
20, 50, // radius 20px untuk cluster < 50 points
30, 100, // radius 30px untuk cluster < 100 points
40 // radius 40px untuk cluster >= 100 points
],
'circle-opacity': 0.8
}
});
2. Lazy load GeoJSON: Untuk dataset besar (10MB+), jangan load semua sekaligus. Pakai fetch() dengan bounding box filter di backend, atau gunakan Mapbox tilesets yang sudah ter-tile otomatis.
3. Debounce event handler: Event moveend dan zoomend fire sangat sering saat user drag peta. Selalu debounce handler kalau ada API call atau heavy computation di dalamnya:
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
map.on('moveend', debounce(() => {
const bounds = map.getBounds();
fetch(`/api/locations?bbox=${bounds.toArray().join(',')}`)
.then(r => r.json())
.then(data => {
map.getSource('locations').setData(data);
});
}, 300));
Kesimpulan
Mapbox GL JS itu powerful banget untuk bikin WebGIS modern. Dengan WebGL rendering, 3D terrain, custom styling, dan data-driven visualization, kamu bisa bikin peta interaktif yang nggak kalah dari aplikasi map professional. Dan yang paling penting, gratis tier-nya cukup generous untuk project small-medium.
Kalau kamu lagi develop WebGIS atau butuh peta interaktif di website, cobain Mapbox GL JS. Setup-nya cuma butuh beberapa menit, dan hasilnya langsung kelihatan professional. Sudah pernah coba Mapbox atau masih setia dengan Leaflet? Share pengalaman kamu di kolom komentar!