menambahkan fitur heatmap dan memperbarui ui layer control
This commit is contained in:
@@ -282,13 +282,53 @@ html, body {
|
||||
top: 0; bottom: 0; left: 0; right: 0;
|
||||
}
|
||||
|
||||
/* ===== LAYER CONTROL ===== */
|
||||
.leaflet-control-layers {
|
||||
border-radius: 10px !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 2px 12px rgba(0,0,0,0.12) !important;
|
||||
font-family: 'Segoe UI', Arial, sans-serif !important;
|
||||
font-size: 13px !important;
|
||||
/* ===== LAYER CONTROL DI SIDEBAR ===== */
|
||||
.layer-control {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 4px 2px;
|
||||
}
|
||||
|
||||
.layer-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
color: #444;
|
||||
cursor: pointer;
|
||||
padding: 4px 2px;
|
||||
border-radius: 6px;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.layer-item:hover {
|
||||
background: #f0f4f8;
|
||||
}
|
||||
|
||||
.layer-item input[type="checkbox"] {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
cursor: pointer;
|
||||
accent-color: #1B2A4A;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.layer-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.layer-radius-icon {
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border: 2px dashed #8e44ad;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.map-legend {
|
||||
@@ -327,4 +367,13 @@ html, body {
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.layer-heatmap-icon {
|
||||
width: 16px;
|
||||
height: 12px;
|
||||
border-radius: 4px;
|
||||
background: linear-gradient(to right, #3498db, #f1c40f, #e67e22, #e74c3c);
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -11,14 +11,21 @@ const layerTidakTercakup = L.layerGroup().addTo(map);
|
||||
const layerIbadah = L.layerGroup().addTo(map);
|
||||
const layerRadius = L.layerGroup().addTo(map);
|
||||
|
||||
// 2. DAFTARKAN LAYER-LAYER TERSEBUT KE DALAM CONTROL PANEL
|
||||
const overlays = {
|
||||
"<span style='color:#27ae60'>⌂</span> Prasejahtera Tercakup": layerTercakup,
|
||||
"<span style='color:#e74c3c'>⌂</span> Prasejahtera Tidak Tercakup": layerTidakTercakup,
|
||||
"<i class='fa-solid fa-place-of-worship' style='color:purple'></i> Rumah Ibadah": layerIbadah,
|
||||
"○ Radius Jangkauan": layerRadius,
|
||||
};
|
||||
L.control.layers(null, overlays, { collapsed: false }).addTo(map);
|
||||
function toggleLayer(namaLayer, checkbox) {
|
||||
const layers = {
|
||||
'tercakup': layerTercakup,
|
||||
'tidakTercakup': layerTidakTercakup,
|
||||
'ibadah': layerIbadah,
|
||||
'radius': layerRadius,
|
||||
};
|
||||
|
||||
if (checkbox.checked) {
|
||||
layers[namaLayer].addTo(map);
|
||||
} else {
|
||||
map.removeLayer(layers[namaLayer]);
|
||||
}
|
||||
}
|
||||
|
||||
let legend = L.control({ position: 'topright' });
|
||||
legend.onAdd = function() {
|
||||
let div = L.DomUtil.create('div', 'map-legend');
|
||||
@@ -38,6 +45,14 @@ legend.onAdd = function() {
|
||||
<div class="legend-item"><span class="legend-dot" style="background:#e74c3c;"></span> Klenteng</div>
|
||||
<hr style="margin:6px 0; border-color:#eee;">
|
||||
<div class="legend-item"><span class="legend-radius"></span> Radius Jangkauan</div>
|
||||
<div class="legend-item">
|
||||
<span style="
|
||||
width:40px; height:10px;
|
||||
background: linear-gradient(to right, #3498db, #f1c40f, #e67e22, #e74c3c);
|
||||
border-radius:4px; display:inline-block; flex-shrink:0;
|
||||
"></span>
|
||||
Heatmap Kemiskinan
|
||||
</div>
|
||||
`;
|
||||
return div;
|
||||
};
|
||||
@@ -372,6 +387,12 @@ function loadDB() {
|
||||
daftarMarker['p_' + rumah.id] = marker;
|
||||
});
|
||||
|
||||
// Perbarui heatmap setelah data prasejahtera termuat
|
||||
if (document.getElementById('checkbox-heatmap')?.checked) {
|
||||
buatHeatmap();
|
||||
heatmapAktif = true;
|
||||
}
|
||||
|
||||
// Muat ibadah SETELAH prasejahtera selesai
|
||||
loadIbadah();
|
||||
});
|
||||
@@ -391,6 +412,8 @@ function refreshPeta() {
|
||||
|
||||
// 3. Panggil ulang data terbaru dari database
|
||||
loadDB();
|
||||
|
||||
if (heatmapAktif) buatHeatmap();
|
||||
}
|
||||
|
||||
// --- EVENT KLIK PETA ---
|
||||
@@ -864,4 +887,45 @@ function simpanEditIbadah(id) {
|
||||
Toast.fire({ icon: 'error', title: 'Gagal: ' + (data.message || 'Error') });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- HEATMAP ---
|
||||
let heatmapLayer = null;
|
||||
let heatmapAktif = false;
|
||||
|
||||
function toggleHeatmap() {
|
||||
let checkbox = document.getElementById('checkbox-heatmap');
|
||||
|
||||
if (checkbox.checked) {
|
||||
buatHeatmap();
|
||||
heatmapAktif = true;
|
||||
} else {
|
||||
if (heatmapLayer) map.removeLayer(heatmapLayer);
|
||||
heatmapAktif = false;
|
||||
}
|
||||
}
|
||||
|
||||
function buatHeatmap() {
|
||||
// Ambil koordinat dari dataPrasejahtera yang sudah ada di memori
|
||||
let points = [];
|
||||
for (let id in dataPrasejahtera) {
|
||||
let p = dataPrasejahtera[id];
|
||||
points.push([p.lat, p.lng, 1]); // [lat, lng, intensity]
|
||||
}
|
||||
|
||||
// Hapus layer lama kalau ada
|
||||
if (heatmapLayer) map.removeLayer(heatmapLayer);
|
||||
|
||||
heatmapLayer = L.heatLayer(points, {
|
||||
radius: 35, // ukuran area panas per titik
|
||||
blur: 25, // tingkat kehalusan gradasi
|
||||
maxZoom: 17, // zoom maksimal sebelum intensitas penuh
|
||||
max: 1.0,
|
||||
gradient: {
|
||||
0.2: '#3498db', // biru = kepadatan rendah
|
||||
0.5: '#f1c40f', // kuning = kepadatan sedang
|
||||
0.8: '#e67e22', // oranye = kepadatan tinggi
|
||||
1.0: '#e74c3c' // merah = kepadatan sangat tinggi
|
||||
}
|
||||
}).addTo(map);
|
||||
}
|
||||
@@ -56,6 +56,37 @@ $role = $isLoggedIn ? $_SESSION['role'] : 'viewer';
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<span class="sidebar-label">Visualisasi</span>
|
||||
|
||||
<div class="layer-control">
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('tercakup', this)">
|
||||
<span class="layer-dot" style="background:#27ae60;"></span>
|
||||
Prasejahtera Tercakup
|
||||
</label>
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('tidakTercakup', this)">
|
||||
<span class="layer-dot" style="background:#e74c3c;"></span>
|
||||
Prasejahtera Tidak Tercakup
|
||||
</label>
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('ibadah', this)">
|
||||
<span class="layer-dot" style="background:#9b59b6;"></span>
|
||||
Rumah Ibadah
|
||||
</label>
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('radius', this)">
|
||||
<span class="layer-radius-icon"></span>
|
||||
Radius Jangkauan
|
||||
</label>
|
||||
<label class="layer-item" style="cursor:pointer;">
|
||||
<input type="checkbox" id="checkbox-heatmap" checked onchange="toggleHeatmap()">
|
||||
<span class="layer-heatmap-icon"></span>
|
||||
Heatmap Kemiskinan
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<a href="logout.php" class="btn-logout">
|
||||
<i class="fa-solid fa-right-from-bracket"></i> Logout
|
||||
@@ -70,6 +101,37 @@ $role = $isLoggedIn ? $_SESSION['role'] : 'viewer';
|
||||
<i class="fa-solid fa-right-to-bracket"></i> Login
|
||||
</a>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<span class="sidebar-label">Visualisasi</span>
|
||||
|
||||
<div class="layer-control">
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('tercakup', this)">
|
||||
<span class="layer-dot" style="background:#27ae60;"></span>
|
||||
Prasejahtera Tercakup
|
||||
</label>
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('tidakTercakup', this)">
|
||||
<span class="layer-dot" style="background:#e74c3c;"></span>
|
||||
Prasejahtera Tidak Tercakup
|
||||
</label>
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('ibadah', this)">
|
||||
<span class="layer-dot" style="background:#9b59b6;"></span>
|
||||
Rumah Ibadah
|
||||
</label>
|
||||
<label class="layer-item">
|
||||
<input type="checkbox" checked onchange="toggleLayer('radius', this)">
|
||||
<span class="layer-radius-icon"></span>
|
||||
Radius Jangkauan
|
||||
</label>
|
||||
<label class="layer-item" style="cursor:pointer;">
|
||||
<input type="checkbox" id="checkbox-heatmap" checked onchange="toggleHeatmap()">
|
||||
<span class="layer-heatmap-icon"></span>
|
||||
Heatmap Kemiskinan
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
@@ -88,6 +150,7 @@ $role = $isLoggedIn ? $_SESSION['role'] : 'viewer';
|
||||
const ROLE = '<?= $role ?>';
|
||||
</script>
|
||||
|
||||
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
|
||||
<script src="assets/js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user