GIS 04 Aug 2026 82 views 0 komentar

Leaflet.js dari Pemula ke Pro - Membuat Peta Interaktif di Website yang Cepat dan Ringan

Leaflet.js dari Pemula ke Pro - Membuat Peta Interaktif di Website yang Cepat dan Ringan

Saat pertama kali diminta bikin peta interaktif untuk website kantor, saya langsung panik. Google Maps API ribet, harus daftar API key, ada billing, dan loading-nya berat banget. Padahal yang dibutuhkan cuma peta sederhana yang bisa di-zoom, ada marker, dan user bisa klik untuk lihat info. Setelah cari-cari, ketemu Leaflet.js dan sejak itu jadi senjata utama untuk semua proyek peta di web.

Leaflet.js itu library JavaScript open-source yang ringan (hanya ~40KB gzip), cepat, dan mobile-friendly. Dibuat oleh Vladimir Agafonkin (mantan developer Mapbox), library ini dipakai oleh jutaan website di seluruh dunia termasuk GitHub, Pinterest, dan banyak portal berita. Yang paling menarik? Leaflet pakai tile OpenStreetMap sebagai default gratis, tanpa API key, dan bisa dipakai tanpa batasan rate-limit.

Di artikel ini saya akan tunjukin cara bikin peta interaktif dari nol, termasuk beberapa fitur lanjutan yang jarang dibahas di tutorial biasa. Kita akan cover:

  • Instalasi dan setup CDN, npm, atau manual
  • Marker dan popup bikin penanda lokasi yang interaktif
  • Tile layer custom ganti tampilan peta sesuai selera
  • GeoJSON render data spasial kompleks
  • Marker clustering handle ribuan marker tanpa lag
  • Event handling interaksi dinamis seperti click, hover, drag

Kenapa Harus Leaflet.js?

Sebelum masuk ke kode, ada baiknya kita pahami kenapa Leaflet layak dipilih dibanding alternatif lain:

  • Ukuran kecil: ~40KB gzip dibanding Google Maps API (~100KB+) atau Mapbox GL JS (~200KB+)
  • Tanpa API key: OpenStreetMap tiles gratis dan tidak perlu registrasi
  • Mobile-first: Support touch gestures, pinch-to-zoom, dan swipe dari awal
  • Plugin ecosystem: Ratusan plugin untuk marker clustering, heatmaps, draw tools, dll
  • Dokumentasi lengkap: Dokumentasi resmi sangat jelas dengan contoh yang langsung bisa dijalankan
  • Berat browser ringan: Tidak memaksa WebGL, jalan di browser lama sekalipun

Untuk benchmark singkat, saya tes load time di halaman dengan 100 marker:


# Leaflet.js
# Time to Interactive: ~800ms
# Memory usage: ~25MB

# Google Maps JavaScript API
# Time to Interactive: ~1500ms
# Memory usage: ~45MB

# Mapbox GL JS
# Time to Interactive: ~1200ms
# Memory usage: ~35MB

Angka ini tentu berbeda-beda tergantung koneksi dan device, tapi trennya konsisten Leaflet lebih ringan di semua metrik.

Instalasi dan Setup Pertama

Cara paling cepat mulai pakai Leaflet adalah lewat CDN. Cukup tambahkan dua baris di HTML CSS dan JavaScript. Tidak perlu build tool, tidak perlu npm install.


<!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 Leaflet</title>
 <!-- Leaflet CSS -->
 <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
 integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
 crossorigin="" />
</head>
<body>
 <div id="map" style="height: 500px; width: 100%;"></div>

 <!-- Leaflet JS -->
 <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
 integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
 crossorigin=""></script>
 <script>
 // Inisialisasi peta
 var map = L.map('map').setView([-6.2088, 106.8456], 13);

 // Tambah tile layer OpenStreetMap
 L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
 maxZoom: 19,
 attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
 }).addTo(map);
 </script>
</body>
</html>

Kode di atas sudah cukup untuk menampilkan peta interaktif di Jakarta. User bisa zoom in/out, pan ke segala arah, dan ada atribusi OpenStreetMap di pojok kanan bawah. Total kode yang ditulis cuma sekitar 15 baris itu sudah termasuk HTML boilerplate.

Untuk project yang lebih serius, pakai package manager lebih rapi:


# npm
npm install leaflet

# yarn
yarn add leaflet

# Import di JavaScript module
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';

Marker dan Popup Bikin Lokasi Bisa Diklik

Marker itu penanda di peta. Di Leaflet, bikin marker cuma butuh satu baris tapi kita bisa bikin jauh lebih interaktif dengan popup custom.


// Marker default (ikon biru standar)
var marker = L.marker([-6.2088, 106.8456]).addTo(map);

// Popup yang muncul saat marker diklik
marker.bindPopup(`
 <div style="font-family: Arial, sans-serif;">
 <h4 style="margin: 0 0 5px 0; color: #333;"> Jakarta Pusat</h4>
 <p style="margin: 0; color: #666; font-size: 13px;">
 Ibu kota Indonesia dengan populasi 10+ juta jiwa.
 </p>
 <a href="https://jakarta.go.id" target="_blank"
 style="color: #0078A8; font-size: 12px;">Lihat detail </a>
 </div>
`);

// Buka popup otomatis saat halaman load
marker.openPopup();

Yang menarik, popup Leaflet mendukung HTML lengkap kamu bisa masukkan gambar, tombol, form, bahkan iframe. Tapi jangan kebanyakan juga, karena popup yang terlalu berat bisa bikin performa menurun di mobile.

Untuk marker custom dengan ikon sendiri:


// Custom icon
var customIcon = L.icon({
 iconUrl: '/assets/images/marker-icon.png',
 shadowUrl: '/assets/images/marker-shadow.png',
 iconSize: [25, 41],
 iconAnchor: [12, 41],
 popupAnchor: [1, -34]
});

var marker = L.marker([-6.1751, 106.8650], { icon: customIcon })
 .addTo(map)
 .bindPopup('<strong>Monas</strong><br>Monumen Nasional');

Penting: iconAnchor menentukan titik mana dari icon yang tepat menunjuk ke koordinat. Default-nya di tengah-bawah, yang bagus untuk pin/pointer. Kalau icon bulat, set iconAnchor ke tengah-tengah: [iconSize[0]/2, iconSize[1]/2].

Tile Layer Custom Gampil Tampilan Peta

Default OpenStreetMap memang bagus, tapi kadang butuh tampilan yang beda misal peta gelap untuk dashboard monitoring, atau peta topografi untuk aplikasi GIS.


// Peta gelap (dark mode) cocok untuk dashboard
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
 attribution: '&copy; <a href="https://carto.com/">CARTO</a>',
 subdomains: 'abcd',
 maxZoom: 19
}).addTo(map);

// Peta terang minimalis
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
 attribution: '&copy; <a href="https://carto.com/">CARTO</a>',
 subdomains: 'abcd',
 maxZoom: 19
}).addTo(map);

// Peta satelit dari ESRI
L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
 attribution: '&copy; Esri',
 maxZoom: 18
}).addTo(map);

Tips: kalau mau bikin fitur ganti layer, pakai L.control.layers():


var osmLayer = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
 attribution: '&copy; OpenStreetMap'
});
var darkLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
 attribution: '&copy; CARTO'
});

// Control panel di pojok kanan atas
L.control.layers({
 ' OpenStreetMap': osmLayer,
 ' Dark Mode': darkLayer
}).addTo(map);

GeoJSON Render Data Spasial Kompleks

GeoJSON itu format standar untuk data geografis. Di Leaflet, render GeoJSON semudah memanggil satu fungsi tapi ada beberapa trik yang perlu diketahui supaya performanya tetap bagus dan interaksinya mantap.


// Data GeoJSON contoh batas wilayah
var geojsonLayer = L.geoJSON({
 "type": "Feature",
 "geometry": {
 "type": "Polygon",
 "coordinates": [[
 [106.75, -6.15],
 [106.90, -6.15],
 [106.90, -6.25],
 [106.75, -6.25],
 [106.75, -6.15]
 ]]
 },
 "properties": {
 "name": "Jakarta Pusat",
 "population": "2300000"
 }
}, {
 // Style untuk polygon
 style: function(feature) {
 return {
 color: '#0078A8',
 weight: 2,
 opacity: 0.8,
 fillColor: '#0078A8',
 fillOpacity: 0.2
 };
 },
 // Saat polygon diklik
 onEachFeature: function(feature, layer) {
 layer.bindPopup(
 '<strong>' + feature.properties.name + '</strong><br>' +
 'Populasi: ' + feature.properties.population
 );
 }
}).addTo(map);

// Fit map ke extent GeoJSON
map.fitBounds(geojsonLayer.getBounds());

Kalau GeoJSON file-nya besar (di atas 1MB), jangan langsung render semua ke peta. Gunakan simplifikasi geometri supaya tidak lag.

Marker Clustering Handle Ribuan Marker

Ini masalah klasik di GIS web: kalau ada 5000 marker, peta langsung ngelag. Solusinya pakai Leaflet.markercluster plugin marker yang berdekatan otomatis dikelompokkan jadi satu angka, dan saat user zoom in, bar pecah jadi marker individual.


<!-- Tambahkan CSS markercluster -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/MarkerCluster.css" />
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/MarkerCluster.Default.css" />

<!-- JS setelah Leaflet -->
<script src="https://unpkg.com/[email protected]/dist/leaflet.markercluster.js"></script>

// Buat cluster group
var markers = L.markerClusterGroup({
 maxClusterRadius: 50,
 spiderfyOnMaxZoom: true,
 showCoverageOnHover: false
});

// Tambahkan ribuan marker
var locations = [
 { lat: -6.2088, lng: 106.8456, name: 'Kantor A' },
 { lat: -6.2100, lng: 106.8460, name: 'Kantor B' },
 { lat: -6.1950, lng: 106.8300, name: 'Kantor C' }
];

locations.forEach(function(loc) {
 var marker = L.marker([loc.lat, loc.lng])
 .bindPopup('<strong>' + loc.name + '</strong>');
 markers.addLayer(marker);
});

map.addLayer(markers);

Performance test saya dengan 10.000 marker di Chrome:

  • Tanpa clustering: page freeze 3-5 detik, frame rate drops ke 5 FPS
  • Dengan clustering: page load normal, 60 FPS, zoom smooth

Event Handling Interaksi Dinamis

Leaflet punya sistem event yang mirip DOM events. Ini yang bikin peta bisa jadi benar-benar interaktif.


// Klik di mana saja di peta ambil koordinat
map.on('click', function(e) {
 console.log('Koordinat:', e.latlng.lat, e.latlng.lng);

 // Tambah marker baru saat user klik
 L.marker([e.latlng.lat, e.latlng.lng])
 .addTo(map)
 .bindPopup('Marker baru di [' + e.latlng.lat.toFixed(4) +
 ', ' + e.latlng.lng.toFixed(4) + ']')
 .openPopup();
});

// Event zoom tampilkan level zoom saat ini
map.on('zoomend', function() {
 console.log('Zoom level:', map.getZoom());
});

// Double-click zoom (default: aktif, bisa dimatikan)
map.doubleClickZoom.disable();

Fitur lain yang sering saya pakai: locateAndSetView untuk auto-center peta ke lokasi user:


// Minta lokasi GPS user
map.locate({ setView: true, maxZoom: 16 });

map.on('locationfound', function(e) {
 L.marker(e.latlng)
 .addTo(map)
 .bindPopup(' Lokasi Anda')
 .openPopup();

 // Tampilkan radius akurasi
 L.circle(e.latlng, { radius: e.accuracy / 2 })
 .addTo(map);
});

map.on('locationerror', function(e) {
 console.log('Error:', e.message);
 // Fallback ke Jakarta
 map.setView([-6.2088, 106.8456], 13);
});

Leaflet dengan CodeIgniter 4 Integrasi di Backend

Kalau kamu pakai CodeIgniter 4, integrasi Leaflet sangat mudah. Controller kirim data GeoJSON dari MySQL, view render peta:


// Di controller (misal Maps.php)
public function index()
{
 $model = new \App\Models\M_maps();
 $locations = $model->findAll();

 $geojson = [
 'type' => 'FeatureCollection',
 'features' => []
 ];

 foreach ($locations as $loc) {
 $geojson['features'][] = [
 'type' => 'Feature',
 'geometry' => [
 'type' => 'Point',
 'coordinates' => [(float)$loc['longitude'], (float)$loc['latitude']]
 ],
 'properties' => [
 'name' => $loc['name'],
 'description' => $loc['description'],
 'category' => $loc['category']
 ]
 ];
 }

 return view('maps/index', ['geojson' => json_encode($geojson)]);
}

<!-- View: maps/index.php -->
<div id="map" style="height: 600px;"></div>
<script>
var map = L.map('map').setView([-6.2088, 106.8456], 11);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
 attribution: '&copy; OSM'
}).addTo(map);

var geojson = <?= $geojson ?>;

L.geoJSON(geojson, {
 onEachFeature: function(feature, layer) {
 layer.bindPopup(
 '<h4>' + feature.properties.name + '</h4>' +
 '<p>' + feature.properties.description + '</p>'
 );
 }
}).addTo(map);
</script>

Cara kirim data dari PHP ke JavaScript via json_encode() sangat reliable tidak perlu fetch API tambahan, data langsung embedded di halaman. Untuk data ribuan baris, pertimbangkan pakai AJAX agar halaman tetap cepat render.

Tips Performance untuk Peta Besar

Dari pengalaman nge-handle proyek peta dengan ribuan data point, ini beberapa tips yang bikin beda:

  • Pakai canvas renderer: Default SVG lambat di atas 1000 elemen. Tambah {renderer: L.canvas()} saat inisialisasi peta atau saat bikin GeoJSON layer
  • Lazy load tile: Peta tidak perlu render semua zoom level sekaligus. Set maxZoom yang wajar kebanyakan peta web cukup sampai zoom level 16-17
  • Debounce event handler: Event move dan mousemove fire sangat sering. Gunakan debounce/throttle supaya handler tidak dipanggil ratusan kali per detik
  • Cluster radius yang tepat: Terlalu kecil = terlalu banyak cluster. Terlalu besar = cluster terlalu crowded. Angka 50-80 meter adalah sweet spot untuk peta kota
  • Hapus layer dari DOM: Kalau user navigasi ke area lain, hapus marker lama yang sudah tidak terlihat untuk free memory

Kesimpulan

Leaflet.js itu pilihan terbaik untuk peta interaktif di web kalau kamu butuh sesuatu yang cepat, ringan, dan tanpa biaya. Tidak perlu API key, dokumentasi lengkap, dan ekosistem plugin-nya kaya. Dari peta sederhana dengan satu marker sampai dashboard GIS dengan ribuan data point, Leaflet bisa handle semuanya.

Poin penting yang harus diingat: mulai dari yang sederhana dulu. Bikin peta dengan satu marker, pastikan jalan, baru tambah fitur satu per satu. Jangan langsung paksa render 10.000 marker di awal build incrementally dan test di mobile sejak awal karena sebagian besar user peta sekarang akses dari HP.

Sudah pernah pakai Leaflet.js untuk proyek? Atau masih stuck pakai Google Maps API yang ribet itu? Cerita di komologi yuk mana tahu ada tips lain yang bisa sharing!


Bagikan artikel ini:

Komentar (0)

Belum ada komentar. Jadilah yang pertama memberikan tanggapan!

Tinggalkan Komentar