341 lines
7.9 KiB
HTML
341 lines
7.9 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>WEB GIS FINAL</title>
|
|
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw/dist/leaflet.draw.css"/>
|
|
|
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
|
<script src="https://unpkg.com/leaflet-draw/dist/leaflet.draw.js"></script>
|
|
<script src="https://unpkg.com/leaflet-geometryutil"></script>
|
|
|
|
<style>
|
|
#map { height: 100vh; }
|
|
|
|
#searchBox{
|
|
position:absolute;
|
|
top:10px;
|
|
left:260px;
|
|
z-index:999;
|
|
padding:8px;
|
|
width:250px;
|
|
}
|
|
|
|
.modal {
|
|
display:none;
|
|
position:fixed;
|
|
z-index:999;
|
|
left:0;top:0;
|
|
width:100%;height:100%;
|
|
background:rgba(0,0,0,0.5);
|
|
}
|
|
.modal-content{
|
|
background:white;
|
|
padding:20px;
|
|
width:300px;
|
|
margin:120px auto;
|
|
border-radius:10px;
|
|
text-align:center;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<input type="text" id="searchBox" placeholder="Cari semua data...">
|
|
<div id="map"></div>
|
|
|
|
<div id="formModal" class="modal">
|
|
<div class="modal-content">
|
|
<h3 id="formTitle"></h3>
|
|
<input type="text" id="input1"><br>
|
|
<select id="input2"></select><br>
|
|
<button onclick="submitForm()">Simpan</button>
|
|
<button onclick="closeForm()">Batal</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// ================= MAP =================
|
|
var map = L.map('map').setView([-0.05,109.34],13);
|
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
|
|
|
|
var drawnItems = new L.FeatureGroup();
|
|
map.addLayer(drawnItems);
|
|
|
|
let semuaLayer = [];
|
|
let currentLayer = null;
|
|
let currentType = null;
|
|
|
|
// ================= WARNA =================
|
|
function warnaJalan(s){
|
|
return s=="Nasional"?"red":s=="Provinsi"?"blue":"green";
|
|
}
|
|
|
|
function warnaParsil(s){
|
|
return s=="SHM"?"yellow":
|
|
s=="HGB"?"orange":
|
|
s=="HGU"?"brown":
|
|
"purple";
|
|
}
|
|
|
|
// ================= FORMAT =================
|
|
function formatMeter(m){ return m.toFixed(2)+" m"; }
|
|
function formatMeter2(m){ return m.toFixed(2)+" m²"; }
|
|
|
|
// ================= FORM =================
|
|
function openForm(type, layer){
|
|
currentLayer = layer;
|
|
currentType = type;
|
|
|
|
document.getElementById("formModal").style.display="block";
|
|
|
|
let select = document.getElementById("input2");
|
|
select.innerHTML="";
|
|
|
|
if(type=="jalan"){
|
|
formTitle.innerText="Input Jalan";
|
|
input1.placeholder="Nama Jalan";
|
|
|
|
["Nasional","Provinsi","Kabupaten"].forEach(v=>{
|
|
let o=document.createElement("option");
|
|
o.value=v;o.text=v;
|
|
select.appendChild(o);
|
|
});
|
|
}
|
|
|
|
else if(type=="parsil"){
|
|
formTitle.innerText="Input Parsil";
|
|
input1.placeholder="Nama Pemilik";
|
|
|
|
["SHM","HGB","HGU","HP"].forEach(v=>{
|
|
let o=document.createElement("option");
|
|
o.value=v;o.text=v;
|
|
select.appendChild(o);
|
|
});
|
|
}
|
|
|
|
else if(type=="rusak"){
|
|
formTitle.innerText="Jalan Rusak";
|
|
input1.placeholder="Keterangan";
|
|
|
|
["Ringan","Sedang","Berat"].forEach(v=>{
|
|
let o=document.createElement("option");
|
|
o.value=v;o.text=v;
|
|
select.appendChild(o);
|
|
});
|
|
}
|
|
}
|
|
|
|
function closeForm(){
|
|
document.getElementById("formModal").style.display="none";
|
|
input1.value = "";
|
|
currentLayer = null;
|
|
currentType = null;
|
|
// Re-enable draw control
|
|
map.addControl(drawControl);
|
|
}
|
|
|
|
function submitForm(){
|
|
let v1 = input1.value.trim();
|
|
let v2 = input2.value;
|
|
|
|
if(!v1){
|
|
alert("Mohon isi nama/keterangan terlebih dahulu!");
|
|
return;
|
|
}
|
|
|
|
if(!currentLayer || !currentType){
|
|
alert("Tidak ada layer yang dipilih!");
|
|
closeForm();
|
|
return;
|
|
}
|
|
|
|
// Simpan referensi layer sebelum closeForm me-reset currentLayer
|
|
let layer = currentLayer;
|
|
let type = currentType;
|
|
|
|
closeForm();
|
|
|
|
if(type=="jalan") prosesJalan(layer, v1, v2);
|
|
else if(type=="parsil") prosesParsil(layer, v1, v2);
|
|
else if(type=="rusak") prosesRusak(layer, v1, v2);
|
|
}
|
|
|
|
// ================= DRAW =================
|
|
var drawControl = new L.Control.Draw({
|
|
edit:{ featureGroup: drawnItems },
|
|
draw:{
|
|
polyline:true,
|
|
polygon:true,
|
|
rectangle:false,
|
|
circle:false,
|
|
marker:true
|
|
}
|
|
});
|
|
map.addControl(drawControl);
|
|
|
|
map.on('draw:created', function(e){
|
|
var layer = e.layer;
|
|
drawnItems.addLayer(layer);
|
|
|
|
// Disable draw sementara sampai form disubmit
|
|
map.removeControl(drawControl);
|
|
|
|
if(e.layerType=="polyline") openForm("jalan",layer);
|
|
if(e.layerType=="polygon") openForm("parsil",layer);
|
|
if(e.layerType=="marker") openForm("rusak",layer);
|
|
});
|
|
|
|
// ================= JALAN =================
|
|
function prosesJalan(layer,nama,status){
|
|
|
|
let latlngs = layer.getLatLngs();
|
|
let panjang=0;
|
|
for(let i=0;i<latlngs.length-1;i++){
|
|
panjang += latlngs[i].distanceTo(latlngs[i+1]);
|
|
}
|
|
|
|
layer.setStyle({color:warnaJalan(status)});
|
|
|
|
fetch('save_jalan.php',{
|
|
method:'POST',
|
|
headers:{'Content-Type':'application/json'},
|
|
body:JSON.stringify({nama,status,panjang,geometry:layer.toGeoJSON().geometry})
|
|
})
|
|
.then(r=>r.json())
|
|
.then(res=> { if(res.success) layer.id=res.id; else console.error('save_jalan error:',res.error); });
|
|
|
|
layer.bindPopup(`<b>Jalan</b><br>${nama}<br>Panjang: ${formatMeter(panjang)}`);
|
|
|
|
semuaLayer.push({layer:layer,nama:nama});
|
|
}
|
|
|
|
// ================= PARSIL =================
|
|
function prosesParsil(layer,pemilik,status){
|
|
|
|
let luas = L.GeometryUtil.geodesicArea(layer.getLatLngs()[0]);
|
|
|
|
layer.setStyle({color:warnaParsil(status)});
|
|
|
|
fetch('save_parsil.php',{
|
|
method:'POST',
|
|
headers:{'Content-Type':'application/json'},
|
|
body:JSON.stringify({pemilik,status,luas,geometry:layer.toGeoJSON().geometry})
|
|
})
|
|
.then(r=>r.json())
|
|
.then(res=> { if(res.success) layer.id=res.id; else console.error('save_parsil error:',res.error); });
|
|
|
|
layer.bindPopup(`<b>Parsil</b><br>${pemilik}<br>Luas: ${formatMeter2(luas)}`);
|
|
|
|
semuaLayer.push({layer:layer,nama:pemilik});
|
|
}
|
|
|
|
// ================= RUSAK =================
|
|
function prosesRusak(layer,keterangan,tingkat){
|
|
|
|
let icon = L.icon({
|
|
iconUrl: tingkat=="Ringan"?
|
|
"https://maps.google.com/mapfiles/ms/icons/green-dot.png":
|
|
tingkat=="Sedang"?
|
|
"https://maps.google.com/mapfiles/ms/icons/yellow-dot.png":
|
|
"https://maps.google.com/mapfiles/ms/icons/red-dot.png",
|
|
iconSize:[25,41],
|
|
iconAnchor:[12,41]
|
|
});
|
|
|
|
layer.setIcon(icon);
|
|
|
|
fetch('save_rusak.php',{
|
|
method:'POST',
|
|
headers:{'Content-Type':'application/json'},
|
|
body:JSON.stringify({keterangan,tingkat,geometry:layer.toGeoJSON().geometry})
|
|
})
|
|
.then(r=>r.json())
|
|
.then(res=> { if(res.success) layer.id=res.id; else console.error('save_rusak error:',res.error); });
|
|
|
|
layer.bindPopup(`<b>Rusak</b><br>${keterangan}<br><b>Tingkat:</b> ${tingkat}`);
|
|
|
|
semuaLayer.push({layer:layer,nama:keterangan});
|
|
}
|
|
|
|
// ================= LOAD =================
|
|
fetch('get_jalan.php').then(r=>r.json()).then(data=>{
|
|
data.forEach(j=>{
|
|
let geo=j.geometry;
|
|
let layer=L.geoJSON(geo,{style:{color:warnaJalan(j.status)}}).addTo(map);
|
|
layer.eachLayer(l=>{
|
|
l.bindPopup(`<b>Jalan</b><br>${j.nama}<br>Panjang: ${formatMeter(j.panjang)}`);
|
|
semuaLayer.push({layer:l,nama:j.nama});
|
|
});
|
|
});
|
|
});
|
|
|
|
fetch('get_parsil.php').then(r=>r.json()).then(data=>{
|
|
data.forEach(p=>{
|
|
let geo=p.geometry;
|
|
let layer=L.geoJSON(geo,{style:{color:warnaParsil(p.status)}}).addTo(map);
|
|
layer.eachLayer(l=>{
|
|
l.bindPopup(`<b>Parsil</b><br>${p.pemilik}<br>Luas: ${formatMeter2(p.luas)}`);
|
|
semuaLayer.push({layer:l,nama:p.pemilik});
|
|
});
|
|
});
|
|
});
|
|
|
|
fetch('get_rusak.php').then(r=>r.json()).then(data=>{
|
|
data.forEach(r=>{
|
|
let geo=r.geometry;
|
|
|
|
let icon = L.icon({
|
|
iconUrl: r.tingkat=="Ringan"?
|
|
"https://maps.google.com/mapfiles/ms/icons/green-dot.png":
|
|
r.tingkat=="Sedang"?
|
|
"https://maps.google.com/mapfiles/ms/icons/yellow-dot.png":
|
|
"https://maps.google.com/mapfiles/ms/icons/red-dot.png",
|
|
iconSize:[25,41],
|
|
iconAnchor:[12,41]
|
|
});
|
|
|
|
let layer=L.geoJSON(geo,{
|
|
pointToLayer:(f,latlng)=>L.marker(latlng,{icon:icon})
|
|
}).addTo(map);
|
|
|
|
layer.eachLayer(l=>{
|
|
l.bindPopup(`<b>Rusak</b><br>${r.keterangan}<br><b>Tingkat:</b> ${r.tingkat}`);
|
|
semuaLayer.push({layer:l,nama:r.keterangan});
|
|
});
|
|
});
|
|
});
|
|
|
|
// ================= SEARCH =================
|
|
document.getElementById("searchBox").addEventListener("keyup",function(){
|
|
|
|
let key=this.value.toLowerCase();
|
|
|
|
semuaLayer.forEach(o=>{
|
|
|
|
let cocok=o.nama.toLowerCase().includes(key);
|
|
|
|
if(o.layer.setStyle){
|
|
o.layer.setStyle({
|
|
opacity:cocok?1:0.1,
|
|
fillOpacity:cocok?0.7:0.1
|
|
});
|
|
}
|
|
|
|
if(o.layer.setOpacity){
|
|
o.layer.setOpacity(cocok?1:0.2);
|
|
}
|
|
|
|
if(cocok){
|
|
try{ map.fitBounds(o.layer.getBounds()); }catch(e){}
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html> |