Initial commit

This commit is contained in:
ocabacaa
2026-06-12 10:11:19 +07:00
commit 9503c2dda4
18 changed files with 1119 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
## Pengembang
**Clara Oxana Azalia**
**NIM:** D1041231051
---
## Tujuan Pengembangan
Proyek ini dibuat sebagai media pembelajaran dan implementasi Sistem Informasi Geografis (SIG) berbasis web untuk pengelolaan data jalan dan parsil tanah di Kota Pontianak.
---
## Cara Menjalankan Aplikasi
1. Jalankan Laragon atau XAMPP.
2. Buat database MySQL.
3. Import struktur tabel yang diperlukan.
4. Atur koneksi database pada file `config/koneksi.php`.
5. Simpan project pada folder web server.
6. Buka browser dan akses:
```text
http://localhost:3000
```
---
## Cara Menggunakan
### Menambah Data Jalan
1. Klik ikon **Draw Polyline**.
2. Gambar jalan pada peta.
3. Masukkan nama jalan dan status jalan.
4. Data akan tersimpan ke database.
### Menambah Data Parsil Tanah
1. Klik ikon **Draw Polygon**.
2. Gambar area parsil tanah pada peta.
3. Masukkan nomor parsil dan status kepemilikan.
4. Data akan tersimpan ke database.
### Mengedit Atribut Data
1. Klik objek jalan atau parsil pada peta.
2. Sidebar edit akan muncul.
3. Ubah atribut yang diperlukan.
4. Klik **Simpan Perubahan**.
### Mengedit Geometri
1. Klik tombol **Edit Layers**.
2. Pilih objek yang ingin diubah.
3. Geser titik geometri sesuai kebutuhan.
4. Klik **Save**.
5. Geometri akan diperbarui secara otomatis.
### Menghapus Data
1. Klik objek jalan atau parsil pada peta.
2. Buka sidebar.
3. Klik **Hapus Data**.
4. Data akan dihapus dari database.
---
## Lisensi
Proyek ini dibuat untuk keperluan pembelajaran, penelitian, dan pengembangan Sistem Informasi Geografis (SIG) berbasis web.
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "webgis_parsiltanah";
$conn = mysqli_connect($host, $user, $pass, $db);
if (!$conn) {
die("Koneksi gagal : " . mysqli_connect_error());
}
+30
View File
@@ -0,0 +1,30 @@
CREATE DATABASE webgis_parsiltanah;
USE webgis_parsiltanah;
CREATE TABLE jalan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(100) NOT NULL,
status_jalan ENUM(
'Jalan Nasional',
'Jalan Provinsi',
'Jalan Kabupaten'
) NOT NULL,
panjang DOUBLE NOT NULL,
geom JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE parsil_tanah (
id INT AUTO_INCREMENT PRIMARY KEY,
nomor_parsil VARCHAR(50) NOT NULL,
status_kepemilikan ENUM(
'SHM',
'HGB',
'HGU',
'HP'
) NOT NULL,
luas DOUBLE NOT NULL,
geom JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
+768
View File
@@ -0,0 +1,768 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGIS Jalan & Parsil Tanah</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css">
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
#map {
width: 100%;
height: 100vh;
}
#sidebar {
position: absolute;
top: 0;
right: -320px;
width: 300px;
height: 100%;
background: #fff;
border-left: 1px solid #ddd;
z-index: 9999;
padding: 20px;
transition: .3s;
overflow-y: auto;
box-shadow: -3px 0 10px rgba(0, 0, 0, .2);
}
#sidebar label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
#sidebar input,
#sidebar select {
box-sizing: border-box;
}
#sidebar button {
width: 100%;
}
#sidebar h3 {
margin-top: 10px;
}
#sidebar button {
padding: 10px;
cursor: pointer;
}
#sidebar.active {
right: 0;
}
#sidebar input,
#sidebar select {
width: 100%;
padding: 8px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
<div id="sidebar">
<button onclick="tutupSidebar()">
Tutup
</button>
<h3>Edit Data</h3>
<input type="hidden" id="edit_id">
<input type="hidden" id="edit_tipe">
<label>Nama / Nomor</label>
<input type="text" id="edit_nama">
<label>Status</label>
<select id="edit_status">
</select>
<br><br>
<button onclick="simpanEdit()" style="
background:#2563eb;
color:white;
border:none;
border-radius:5px;
">
Simpan Perubahan
</button>
<button onclick="hapusData()" style="
background:red;
color:white;
border:none;
border-radius:5px;
margin-top:10px;
">
Hapus Data
</button>
</div>
<script>
var map = L.map('map').setView([-0.0263, 109.3425], 13);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: drawnItems
},
draw: {
marker: false,
circle: false,
rectangle: false,
circlemarker: false,
polyline: true,
polygon: true
}
});
map.addControl(drawControl);
var pontianak = [-0.0263, 109.3425];
var homeControl = L.control({
position: 'topleft'
});
homeControl.onAdd = function() {
var div = L.DomUtil.create('div');
div.innerHTML =
'<button style="padding:8px;">🏠 Home</button>';
div.onclick = function() {
map.setView(pontianak, 13);
};
return div;
};
homeControl.addTo(map);
function warnaJalan(status) {
if (status == "Jalan Nasional") return "red";
if (status == "Jalan Provinsi") return "blue";
if (status == "Jalan Kabupaten") return "green";
return "black";
}
function warnaParsil(status) {
if (status == "SHM") return "green";
if (status == "HGB") return "orange";
if (status == "HGU") return "blue";
if (status == "HP") return "purple";
return "gray";
}
//
// TAMPILKAN JALAN
fetch('jalan/tampil.php')
.then(response => response.json())
.then(data => {
data.forEach(item => {
var geojson = {
type: "Feature",
geometry: JSON.parse(item.geom),
properties: item
};
var layer = L.geoJSON(geojson, {
style: {
color: warnaJalan(item.status_jalan),
weight: 4
}
});
layer.eachLayer(function(l) {
l.id_data = item.id;
l.tipe_data = 'jalan';
l.bindPopup(
"<b>Nama Jalan :</b> " + item.nama_jalan +
"<br><b>Status :</b> " + item.status_jalan +
"<br><b>Panjang :</b> " +
parseFloat(item.panjang).toFixed(2) +
" Meter"
);
drawnItems.addLayer(l);
l.on('click', function() {
document
.getElementById('sidebar')
.classList.add('active');
document
.getElementById('edit_id')
.value = item.id;
document
.getElementById('edit_tipe')
.value = 'jalan';
document
.getElementById('edit_nama')
.value = item.nama_jalan;
document
.getElementById('edit_status')
.innerHTML =
'<option>Jalan Nasional</option>' +
'<option>Jalan Provinsi</option>' +
'<option>Jalan Kabupaten</option>';
document
.getElementById('edit_status')
.value = item.status_jalan;
});
});
});
});
// TAMPILKAN PARSIL
fetch('parsil/tampil.php')
.then(response => response.json())
.then(data => {
data.forEach(item => {
var geojson = {
type: "Feature",
geometry: JSON.parse(item.geom),
properties: item
};
var layer = L.geoJSON(geojson, {
style: {
color: warnaParsil(item.status_kepemilikan),
fillOpacity: 0.5
}
});
layer.eachLayer(function(l) {
l.id_data = item.id;
l.tipe_data = 'parsil';
l.bindPopup(
"<b>Nomor Parsil :</b> " +
item.nomor_parsil +
"<br><b>Status :</b> " +
item.status_kepemilikan +
"<br><b>Luas :</b> " +
parseFloat(item.luas).toFixed(2) +
""
);
drawnItems.addLayer(l);
l.on('click', function() {
document
.getElementById('sidebar')
.classList.add('active');
document
.getElementById('edit_id')
.value = item.id;
document
.getElementById('edit_tipe')
.value = 'parsil';
document
.getElementById('edit_nama')
.value = item.nomor_parsil;
document
.getElementById('edit_status')
.innerHTML =
'<option>SHM</option>' +
'<option>HGB</option>' +
'<option>HGU</option>' +
'<option>HP</option>';
document
.getElementById('edit_status')
.value = item.status_kepemilikan;
});
});
});
});
var layerKecamatan;
fetch('assets/geojson/pontianak.geojson')
.then(response => response.json())
.then(data => {
layerKecamatan = L.geoJSON(data, {
style: {
color: '#2563eb',
weight: 2,
fillColor: '#60a5fa',
fillOpacity: 0.3
},
interactive: false
});
layerKecamatan.addTo(map);
layerKecamatan.bringToBack();
});
// CREATE //
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
drawnItems.addLayer(layer);
var geojson = layer.toGeoJSON();
// JALAN
if (geojson.geometry.type === "LineString") {
var panjang =
turf.length(
geojson, {
units: 'kilometers'
}
) * 1000;
var namaJalan =
prompt("Masukkan Nama Jalan");
var statusJalan =
prompt(
"Masukkan Status Jalan:\n\nJalan Nasional\nJalan Provinsi\nJalan Kabupaten"
);
fetch('jalan/simpan.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'nama_jalan=' + encodeURIComponent(namaJalan) +
'&status_jalan=' + encodeURIComponent(statusJalan) +
'&panjang=' + encodeURIComponent(panjang) +
'&geom=' + encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert("Data Jalan Berhasil Disimpan");
location.reload();
} else {
alert(data.error);
}
});
}
// PARSIL
if (geojson.geometry.type === "Polygon") {
var luas =
turf.area(geojson);
var nomorParsil =
prompt("Masukkan Nomor Parsil");
var statusParsil =
prompt(
"Masukkan Status:\n\nSHM\nHGB\nHGU\nHP"
);
fetch('parsil/simpan.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'nomor_parsil=' + encodeURIComponent(nomorParsil) +
'&status=' + encodeURIComponent(statusParsil) +
'&luas=' + encodeURIComponent(luas) +
'&geom=' + encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert("Data Parsil Berhasil Disimpan");
location.reload();
} else {
alert(data.error);
}
});
}
});
map.on('draw:edited', function(e) {
var layers = e.layers;
layers.eachLayer(function(layer) {
var geojson = layer.toGeoJSON();
if (layer.tipe_data == 'jalan') {
var panjang =
turf.length(
geojson, {
units: 'kilometers'
}
) * 1000;
fetch(
'jalan/update_geom.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + layer.id_data +
'&panjang=' + panjang +
'&geom=' +
encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
}
);
}
if (layer.tipe_data == 'parsil') {
var luas =
turf.area(
geojson
);
fetch(
'parsil/update_geom.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + layer.id_data +
'&luas=' + luas +
'&geom=' +
encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
}
);
}
});
alert(
'Geometry berhasil diperbarui'
);
});
var legend = L.control({
position: 'bottomright'
});
function hapusJalan(id) {
if (!confirm('Hapus data jalan?')) {
return;
}
fetch(
'jalan/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Berhasil dihapus');
location.reload();
}
});
}
function hapusParsil(id) {
if (!confirm('Hapus data parsil?')) {
return;
}
fetch(
'parsil/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Berhasil dihapus');
location.reload();
}
});
}
function simpanEdit() {
var id =
document.getElementById('edit_id').value;
var tipe =
document.getElementById('edit_tipe').value;
var nama =
document.getElementById('edit_nama').value;
var status =
document.getElementById('edit_status').value;
if (tipe == 'jalan') {
fetch('jalan/update.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + id +
'&nama_jalan=' + encodeURIComponent(nama) +
'&status_jalan=' + encodeURIComponent(status)
})
.then(r => r.json())
.then(data => {
alert('Berhasil');
location.reload();
});
}
if (tipe == 'parsil') {
fetch('parsil/update.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + id +
'&nomor_parsil=' + encodeURIComponent(nama) +
'&status=' + encodeURIComponent(status)
})
.then(r => r.json())
.then(data => {
alert('Berhasil');
location.reload();
});
}
}
function tutupSidebar() {
document
.getElementById('sidebar')
.classList.remove('active');
}
function hapusData() {
var id =
document.getElementById('edit_id').value;
var tipe =
document.getElementById('edit_tipe').value;
if (!confirm('Yakin hapus data?')) {
return;
}
if (tipe == 'jalan') {
fetch(
'jalan/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Data berhasil dihapus');
location.reload();
}
});
}
if (tipe == 'parsil') {
fetch(
'parsil/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Data berhasil dihapus');
location.reload();
}
});
}
}
legend.onAdd = function() {
var div = L.DomUtil.create('div');
div.style.background = 'white';
div.style.padding = '10px';
div.innerHTML =
'<b>Jalan</b><br>' +
'<span style="color:red">■</span> Nasional<br>' +
'<span style="color:blue">■</span> Provinsi<br>' +
'<span style="color:green">■</span> Kabupaten<br><br>' +
'<b>Parsil</b><br>' +
'<span style="color:green">■</span> SHM<br>' +
'<span style="color:orange">■</span> HGB<br>' +
'<span style="color:blue">■</span> HGU<br>' +
'<span style="color:purple">■</span> HP';
return div;
};
legend.addTo(map);
</script>
</body>
</html>
+17
View File
@@ -0,0 +1,17 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_GET['id'] ?? '';
$query = mysqli_query(
$conn,
"DELETE FROM jalan
WHERE id='$id'"
);
echo json_encode([
"success" => $query
]);
View File
+29
View File
@@ -0,0 +1,29 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$nama_jalan = $_POST['nama_jalan'] ?? '';
$status_jalan = $_POST['status_jalan'] ?? '';
$panjang = $_POST['panjang'] ?? 0;
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"INSERT INTO jalan (
nama_jalan,
status_jalan,
panjang,
geom
) VALUES (
'$nama_jalan',
'$status_jalan',
'$panjang',
'$geom'
)"
);
echo json_encode([
"success" => $query
]);
+20
View File
@@ -0,0 +1,20 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$query = mysqli_query(
$conn,
"SELECT * FROM jalan"
);
$data = [];
while($row = mysqli_fetch_assoc($query)){
$data[] = $row;
}
echo json_encode($data);
+22
View File
@@ -0,0 +1,22 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$nama_jalan = $_POST['nama_jalan'] ?? '';
$status_jalan = $_POST['status_jalan'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE jalan
SET
nama_jalan = '$nama_jalan',
status_jalan = '$status_jalan'
WHERE id = '$id'"
);
echo json_encode([
"success" => $query
]);
+22
View File
@@ -0,0 +1,22 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$panjang = $_POST['panjang'] ?? 0;
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE jalan
SET
panjang = '$panjang',
geom = '$geom'
WHERE id = '$id'"
);
echo json_encode([
"success" => $query
]);
View File
+17
View File
@@ -0,0 +1,17 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_GET['id'] ?? '';
$query = mysqli_query(
$conn,
"DELETE FROM parsil_tanah
WHERE id='$id'"
);
echo json_encode([
"success" => $query
]);
View File
+29
View File
@@ -0,0 +1,29 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$nomor_parsil = $_POST['nomor_parsil'] ?? '';
$status = $_POST['status'] ?? '';
$luas = $_POST['luas'] ?? 0;
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"INSERT INTO parsil_tanah (
nomor_parsil,
status_kepemilikan,
luas,
geom
) VALUES (
'$nomor_parsil',
'$status',
'$luas',
'$geom'
)"
);
echo json_encode([
"success" => $query
]);
+20
View File
@@ -0,0 +1,20 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$query = mysqli_query(
$conn,
"SELECT * FROM parsil_tanah"
);
$data = [];
while($row = mysqli_fetch_assoc($query)){
$data[] = $row;
}
echo json_encode($data);
+22
View File
@@ -0,0 +1,22 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$nomor_parsil = $_POST['nomor_parsil'] ?? '';
$status = $_POST['status'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE parsil_tanah
SET
nomor_parsil = '$nomor_parsil',
status_kepemilikan = '$status'
WHERE id = '$id'"
);
echo json_encode([
"success" => $query
]);
+28
View File
@@ -0,0 +1,28 @@
<?php
header('Content-Type: application/json');
error_reporting(E_ALL);
ini_set('display_errors',1);
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$luas = $_POST['luas'] ?? '';
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE parsil_tanah
SET
luas='$luas',
geom='$geom'
WHERE id='$id'"
);
echo json_encode([
'success' => $query,
'affected_rows' => mysqli_affected_rows($conn),
'mysql_error' => mysqli_error($conn),
'id' => $id
]);