Files
UAS_WEBGIS_IhyaUlumuddinHar…/project_final/assets/js/public-map.js
T
2026-06-13 11:24:58 +07:00

142 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =========================================================
public-map.js — Peta Publik SKPL
Choropleth (KF-06) + Heatmap (KF-08) + Layer switcher (KF-09)
+ Legenda + Pencarian wilayah (KF-11).
`map` & `APP_BASE` disediakan global oleh peta_publik.php.
========================================================= */
(function () {
const API = APP_BASE + '/api';
let choroplethLayer = null;
let heatLayer = null;
let wilayahFeatures = [];
// ---- Skala warna persentase kemiskinan ----
function colorFor(persen) {
return persen >= 10 ? '#EF4444' // merah — tinggi
: persen >= 5 ? '#FB923C' // oranye — sedang-tinggi
: persen >= 2 ? '#FBBF24' // kuning — sedang
: persen > 0 ? '#A3E635' // hijau muda — rendah
: '#2ECC71'; // hijau — tanpa kasus
}
function styleWilayah(feature) {
const p = feature.properties.persentase_miskin || 0;
return {
fillColor: colorFor(p),
fillOpacity: 0.55,
color: '#374151',
weight: 1.5,
};
}
function popupWilayah(props) {
return `<div style="font-weight:700;margin-bottom:6px;">${props.nama}</div>
<div style="font-size:0.85rem;line-height:1.6;">
Penduduk: <strong>${props.jumlah_penduduk}</strong><br>
Warga miskin: <strong>${props.jumlah_miskin}</strong><br>
Persentase: <strong>${props.persentase_miskin}%</strong>
</div>`;
}
// ---- Choropleth (KF-06) ----
async function loadChoropleth() {
const r = await fetch(`${API}/wilayah.php`);
const j = await r.json();
const data = j.status === 'success' ? j.data : { type: 'FeatureCollection', features: [] };
wilayahFeatures = data.features || [];
choroplethLayer = L.geoJSON(data, {
style: styleWilayah,
onEachFeature: (f, layer) => {
layer.bindPopup(popupWilayah(f.properties));
layer.bindTooltip(f.properties.nama, { sticky: true });
},
}).addTo(map);
if (wilayahFeatures.length) {
map.fitBounds(choroplethLayer.getBounds(), { padding: [40, 40] });
}
return choroplethLayer;
}
// ---- Heatmap (KF-08) ----
async function loadHeatmap() {
const r = await fetch(`${API}/heatmap.php`);
const j = await r.json();
const points = j.status === 'success' ? j.data : [];
heatLayer = L.heatLayer(points, {
radius: 30, blur: 22, maxZoom: 17,
gradient: { 0.2: '#3B82F6', 0.5: '#FBBF24', 0.9: '#EF4444' },
});
return heatLayer;
}
// ---- Legenda (KF-06) ----
function addLegend() {
const legend = L.control({ position: 'bottomleft' });
legend.onAdd = function () {
const div = L.DomUtil.create('div', 'legend');
const grades = [
{ c: '#2ECC71', t: 'Tidak ada kasus' },
{ c: '#A3E635', t: '< 2% miskin' },
{ c: '#FBBF24', t: '2 5%' },
{ c: '#FB923C', t: '5 10%' },
{ c: '#EF4444', t: '> 10% (prioritas)' },
];
div.innerHTML = '<h4>Tingkat Kemiskinan</h4>' +
grades.map(g => `<div><i style="background:${g.c}"></i>${g.t}</div>`).join('');
return div;
};
legend.addTo(map);
}
// ---- Pencarian wilayah (KF-11) ----
function addSearch() {
const ctrl = L.control({ position: 'topright' });
ctrl.onAdd = function () {
const div = L.DomUtil.create('div', 'map-search');
div.innerHTML = `<input type="text" id="searchWilayah" placeholder="🔍 Cari kelurahan..." autocomplete="off">
<div id="searchResults" class="search-results"></div>`;
L.DomEvent.disableClickPropagation(div);
return div;
};
ctrl.addTo(map);
const input = document.getElementById('searchWilayah');
const results = document.getElementById('searchResults');
input.addEventListener('input', function () {
const q = this.value.toLowerCase().trim();
results.innerHTML = '';
if (!q) return;
wilayahFeatures
.filter(f => f.properties.nama.toLowerCase().includes(q))
.slice(0, 6)
.forEach(f => {
const item = document.createElement('div');
item.className = 'search-item';
item.textContent = f.properties.nama;
item.onclick = () => {
const layer = L.geoJSON(f);
map.fitBounds(layer.getBounds(), { padding: [60, 60] });
results.innerHTML = '';
input.value = f.properties.nama;
};
results.appendChild(item);
});
});
}
// ---- Inisialisasi ----
Promise.all([loadChoropleth(), loadHeatmap()]).then(([choro, heat]) => {
// Layer switcher (KF-09)
L.control.layers(null, {
'Batas Kelurahan (Choropleth)': choro,
'Heatmap Kepadatan': heat,
}, { collapsed: false, position: 'topright' }).addTo(map);
addLegend();
addSearch();
});
})();