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

128 lines
5.8 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.
/* =========================================================
skpl-layers.js — Layer SKPL reusable untuk peta login.
Choropleth kelurahan (KF-06) + Heatmap (KF-08) + legenda +
layer switcher overlay (KF-09) + pencarian wilayah (KF-11).
Pakai: panggil attachSkplLayers(map) setelah map dibuat.
Butuh leaflet.heat sudah dimuat di halaman.
========================================================= */
(function () {
function injectStyle() {
if (document.getElementById('skpl-layer-style')) return;
const css = `
.skpl-legend{background:#fff;padding:10px 12px;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,.15);font-size:.76rem;line-height:1.6}
.skpl-legend h4{font-size:.78rem;margin:0 0 6px}
.skpl-legend i{display:inline-block;width:13px;height:13px;border-radius:3px;margin-right:6px;vertical-align:middle}
.skpl-search{background:#fff;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,.15);padding:6px;width:220px}
.skpl-search input{width:100%;border:1px solid #E5E7EB;border-radius:7px;padding:7px 9px;font-size:.83rem;outline:none}
.skpl-search input:focus{border-color:#2563EB}
.skpl-results .item{padding:7px 9px;font-size:.82rem;cursor:pointer;border-radius:6px}
.skpl-results .item:hover{background:#EFF6FF;color:#1D4ED8}`;
const s = document.createElement('style');
s.id = 'skpl-layer-style';
s.textContent = css;
document.head.appendChild(s);
}
function colorFor(p) {
return p >= 10 ? '#EF4444' : p >= 5 ? '#FB923C' : p >= 2 ? '#FBBF24' : p > 0 ? '#A3E635' : '#2ECC71';
}
window.attachSkplLayers = async function (map) {
if (!map || typeof L === 'undefined') return;
injectStyle();
const API = (typeof APP_BASE !== 'undefined' ? APP_BASE : '') + '/api';
let features = [];
// Choropleth
let choro = null;
try {
const j = await (await fetch(`${API}/wilayah.php`)).json();
const data = j.status === 'success' ? j.data : { type: 'FeatureCollection', features: [] };
features = data.features || [];
choro = L.geoJSON(data, {
style: f => ({
fillColor: colorFor(f.properties.persentase_miskin || 0),
fillOpacity: 0.5, color: '#374151', weight: 1.5,
}),
onEachFeature: (f, layer) => {
const p = f.properties;
layer.bindPopup(`<div style="font-weight:700;margin-bottom:6px;">${p.nama}</div>
<div style="font-size:.85rem;line-height:1.6;">
Penduduk: <strong>${p.jumlah_penduduk}</strong><br>
Warga miskin: <strong>${p.jumlah_miskin}</strong><br>
Persentase: <strong>${p.persentase_miskin}%</strong></div>`);
layer.bindTooltip(p.nama, { sticky: true });
},
});
} catch (e) { /* abaikan */ }
// Heatmap
let heat = null;
try {
const j = await (await fetch(`${API}/heatmap.php`)).json();
const pts = j.status === 'success' ? j.data : [];
if (L.heatLayer) {
heat = L.heatLayer(pts, {
radius: 30, blur: 22, maxZoom: 17,
gradient: { 0.2: '#3B82F6', 0.5: '#FBBF24', 0.9: '#EF4444' },
});
}
} catch (e) { /* abaikan */ }
// Layer switcher overlay
const overlays = {};
if (choro) overlays['🗺️ Choropleth Kelurahan'] = choro;
if (heat) overlays['🔥 Heatmap Kepadatan'] = heat;
if (Object.keys(overlays).length) {
L.control.layers(null, overlays, { collapsed: true, position: 'topright' }).addTo(map);
}
// Legenda
const legend = L.control({ position: 'bottomleft' });
legend.onAdd = function () {
const div = L.DomUtil.create('div', 'skpl-legend');
const g = [
['#2ECC71', 'Tidak ada kasus'], ['#A3E635', '< 2%'],
['#FBBF24', '2 5%'], ['#FB923C', '5 10%'], ['#EF4444', '> 10% (prioritas)'],
];
div.innerHTML = '<h4>Tingkat Kemiskinan</h4>' +
g.map(x => `<div><i style="background:${x[0]}"></i>${x[1]}</div>`).join('');
return div;
};
legend.addTo(map);
// Pencarian wilayah (KF-11)
const search = L.control({ position: 'topright' });
search.onAdd = function () {
const div = L.DomUtil.create('div', 'skpl-search');
div.innerHTML = `<input type="text" placeholder="🔍 Cari kelurahan...">
<div class="skpl-results"></div>`;
L.DomEvent.disableClickPropagation(div);
return div;
};
search.addTo(map);
const root = document.querySelector('.skpl-search');
if (root) {
const input = root.querySelector('input');
const res = root.querySelector('.skpl-results');
input.addEventListener('input', function () {
const q = this.value.toLowerCase().trim();
res.innerHTML = '';
if (!q) return;
features.filter(f => f.properties.nama.toLowerCase().includes(q)).slice(0, 6).forEach(f => {
const it = document.createElement('div');
it.className = 'item';
it.textContent = f.properties.nama;
it.onclick = () => {
map.fitBounds(L.geoJSON(f).getBounds(), { padding: [60, 60] });
res.innerHTML = '';
input.value = f.properties.nama;
};
res.appendChild(it);
});
});
}
};
})();