216 lines
8.5 KiB
PHP
216 lines
8.5 KiB
PHP
<?php
|
|
// ==========================================
|
|
// 1. BACKEND: KONEKSI & OTOMATISASI DATABASE
|
|
// ==========================================
|
|
$host = "localhost";
|
|
$user = "root"; // Sesuaikan jika username XAMPP/Laragon kamu berbeda
|
|
$pass = ""; // Sesuaikan jika ada password
|
|
|
|
// Koneksi awal ke MySQL
|
|
$conn = new mysqli($host, $user, $pass);
|
|
if ($conn->connect_error) {
|
|
die("Koneksi ke MySQL Gagal: " . $conn->connect_error);
|
|
}
|
|
|
|
// Buat database otomatis jika belum ada
|
|
$conn->query("CREATE DATABASE IF NOT EXISTS db_webgis_jalan");
|
|
$conn->select_db("db_webgis_jalan");
|
|
|
|
// Buat tabel otomatis jika belum ada
|
|
$conn->query("CREATE TABLE IF NOT EXISTS jalan (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
nama_jalan VARCHAR(150) NOT NULL,
|
|
status_jalan ENUM('Nasional', 'Provinsi', 'Kabupaten') NOT NULL,
|
|
panjang_jalan FLOAT NOT NULL,
|
|
geom TEXT NOT NULL
|
|
)");
|
|
|
|
// ==========================================
|
|
// 2. BACKEND: ROUTING API (SIMPAN & AMBIL)
|
|
// ==========================================
|
|
|
|
// A. Logika Ambil Data (Read)
|
|
if (isset($_GET['aksi']) && $_GET['aksi'] == 'ambil') {
|
|
header('Content-Type: application/json');
|
|
$result = $conn->query("SELECT * FROM jalan");
|
|
$data_jalan = array();
|
|
while($row = $result->fetch_assoc()) {
|
|
$data_jalan[] = $row;
|
|
}
|
|
echo json_encode($data_jalan);
|
|
exit; // Stop eksekusi agar HTML tidak ikut ter-echo
|
|
}
|
|
|
|
// B. Logika Simpan Data (Create)
|
|
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['aksi']) && $_POST['aksi'] == 'simpan') {
|
|
$nama = $_POST['nama'];
|
|
$status = $_POST['status'];
|
|
$panjang = $_POST['panjang'];
|
|
$geom = $_POST['geom'];
|
|
|
|
$stmt = $conn->prepare("INSERT INTO jalan (nama_jalan, status_jalan, panjang_jalan, geom) VALUES (?, ?, ?, ?)");
|
|
$stmt->bind_param("ssds", $nama, $status, $panjang, $geom);
|
|
|
|
if ($stmt->execute()) {
|
|
echo "Sukses";
|
|
} else {
|
|
echo "Gagal: " . $conn->error;
|
|
}
|
|
$stmt->close();
|
|
exit; // Stop eksekusi
|
|
}
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>WebGIS Manajemen Jalan (Single File)</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
<style>
|
|
body { margin: 0; padding: 0; font-family: sans-serif; display: flex; }
|
|
#sidebar { width: 320px; height: 100vh; padding: 20px; box-sizing: border-box; background: #f8f9fa; border-right: 2px solid #ddd; z-index: 1000; }
|
|
#map { width: calc(100% - 320px); height: 100vh; }
|
|
.form-group { margin-bottom: 15px; }
|
|
.form-group label { display: block; margin-bottom: 5px; font-weight: bold; font-size: 14px; }
|
|
.form-group input, .form-group select { width: 100%; padding: 8px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; }
|
|
button { width: 100%; padding: 10px; background: #28a745; color: white; border: none; border-radius: 4px; font-weight: bold; cursor: pointer; }
|
|
button:hover { background: #218838; }
|
|
.info { font-size: 12px; color: #666; margin-top: 10px; line-height: 1.4; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="sidebar">
|
|
<h2>Data Jalan</h2>
|
|
<hr>
|
|
<div class="form-group">
|
|
<label>Nama Jalan</label>
|
|
<input type="text" id="nama_jalan" placeholder="Contoh: Jl. Sudirman">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Status Jalan</label>
|
|
<select id="status_jalan">
|
|
<option value="Nasional">Nasional (Merah)</option>
|
|
<option value="Provinsi">Provinsi (Hijau)</option>
|
|
<option value="Kabupaten">Kabupaten (Biru)</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Panjang (Meter)</label>
|
|
<input type="text" id="panjang_jalan" readonly placeholder="Terhitung otomatis oleh Leaflet">
|
|
</div>
|
|
<button onclick="simpanKeDatabase()">Simpan Jalan</button>
|
|
|
|
<div class="info">
|
|
<strong>Cara Pakai:</strong><br>
|
|
1. Klik beberapa kali di peta untuk menggambar rute jalan.<br>
|
|
2. Panjang jalan akan terhitung otomatis.<br>
|
|
3. Isi Nama & Status, lalu klik Simpan.
|
|
</div>
|
|
</div>
|
|
|
|
<div id="map"></div>
|
|
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
|
|
<script>
|
|
// Inisialisasi Peta (Pusat di Indonesia)
|
|
const map = L.map('map').setView([-2.5, 118], 5);
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
attribution: '© OpenStreetMap'
|
|
}).addTo(map);
|
|
|
|
// Variabel untuk gambar jalan baru
|
|
let koordinatJalan = [];
|
|
let layerJalanBaru = L.polyline([], { color: '#555', weight: 4, dashArray: '5, 10' }).addTo(map);
|
|
|
|
// Fungsi pewarnaan dinamis sesuai perintah dosen
|
|
function dapatkanWarnaJalan(status) {
|
|
switch(status) {
|
|
case 'Nasional': return { color: '#FF0000', weight: 5 }; // Merah
|
|
case 'Provinsi': return { color: '#00FF00', weight: 4 }; // Hijau
|
|
case 'Kabupaten': return { color: '#0000FF', weight: 3 }; // Biru
|
|
default: return { color: '#000000', weight: 2 };
|
|
}
|
|
}
|
|
|
|
// Aksi klik di atas peta (Menggambar + Hitung otomatis)
|
|
map.on('click', function(e) {
|
|
let titik = e.latlng;
|
|
koordinatJalan.push(titik);
|
|
layerJalanBaru.setLatLngs(koordinatJalan);
|
|
|
|
// Hitung panjang otomatis dengan fungsi bawaan Leaflet .distanceTo()
|
|
let totalPanjang = 0;
|
|
for (let i = 0; i < koordinatJalan.length - 1; i++) {
|
|
totalPanjang += koordinatJalan[i].distanceTo(koordinatJalan[i+1]);
|
|
}
|
|
document.getElementById('panjang_jalan').value = totalPanjang.toFixed(2);
|
|
});
|
|
|
|
// Kirim data ke backend (proses INSERT)
|
|
function simpanKeDatabase() {
|
|
let nama = document.getElementById('nama_jalan').value;
|
|
let status = document.getElementById('status_jalan').value;
|
|
let panjang = document.getElementById('panjang_jalan').value;
|
|
|
|
if (!nama || koordinatJalan.length < 2) {
|
|
alert("Masukkan nama jalan dan klik minimal 2 titik di peta!");
|
|
return;
|
|
}
|
|
|
|
// Ubah polyline Leaflet ke bentuk String GeoJSON sesuai validasi dosen
|
|
let geojsonData = JSON.stringify(layerJalanBaru.toGeoJSON().geometry);
|
|
|
|
// AJAX kirim ke file ini sendiri (index.php)
|
|
fetch('index.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
body: `aksi=simpan&nama=${encodeURIComponent(nama)}&status=${status}&panjang=${panjang}&geom=${encodeURIComponent(geojsonData)}`
|
|
})
|
|
.then(res => res.text())
|
|
.then(respon => {
|
|
if (respon.trim() === "Sukses") {
|
|
alert("Data jalan berhasil disimpan!");
|
|
location.reload(); // Reload untuk render ulang peta
|
|
} else {
|
|
alert("Gagal: " + respon);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Ambil data jalan lama dari database (proses READ)
|
|
fetch('index.php?aksi=ambil')
|
|
.then(res => res.json())
|
|
.then(dataJalan => {
|
|
dataJalan.forEach(function(jalan) {
|
|
// Convert teks GeoJSON dari DB balik jadi objek JavaScript
|
|
let geometri = JSON.parse(jalan.geom);
|
|
|
|
let geojsonFeature = {
|
|
"type": "Feature",
|
|
"geometry": geometri,
|
|
"properties": {
|
|
"nama": jalan.nama_jalan,
|
|
"status": jalan.status_jalan,
|
|
"panjang": jalan.panjang_jalan
|
|
}
|
|
};
|
|
|
|
// Gambar ke peta dengan warna dinamis
|
|
L.geoJSON(geojsonFeature, {
|
|
style: function(feature) {
|
|
return dapatkanWarnaJalan(feature.properties.status);
|
|
}
|
|
}).bindPopup(`
|
|
<b>Nama Jalan:</b> ${jalan.nama_jalan}<br>
|
|
<b>Status:</b> Jalan ${jalan.status_jalan}<br>
|
|
<b>Panjang:</b> ${jalan.panjang_jalan} Meter
|
|
`).addTo(map);
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|