GIS Mobile Pro - MVT Masterpiece
+
Unit: 0.00
☰ DASHBOARD
Navigation
📍 Posisi Saya
Survey Tools
📍 Plotting Titik
⬢ Buat Polygon
🧭 Start Tracking
Measurement
📏 Ukur Garis
📐 Ukur Luas Polygon
Advanced & Data
📦 Import SHP (ZIP)
⬇ Export Plotting KML
📊 Tabel Atribut
Gallery Plotting
Belum ada data...
➕ PLOT
✅ SELESAI
✖
/* --- 7. LOGIKA PREVIEW & PENGUKURAN --- */ function updatePreview() { if (currentCoords.length < 2) return; let preview; if (activeMode === 'polygon' || activeMode === 'measure_area') { if (currentCoords.length > 2) { preview = turf.polygon([[...currentCoords, currentCoords[0]]]); if (activeMode === 'measure_area') updateMeasureLabel(turf.area(preview), 'area'); } } else { preview = turf.lineString(currentCoords); if (activeMode.includes('measure')) updateMeasureLabel(turf.length(preview, {units: 'kilometers'}), 'length'); } // Tampilkan preview di peta secara real-time if (preview) { const source = map.getSource('survey-data'); const tempFeatures = [...surveyGeoJSON.features, preview]; source.setData({ 'type': 'FeatureCollection', 'features': tempFeatures }); } } /* --- 8. TRACKING GPS --- */ document.getElementById('btnStartTrack').addEventListener('click', function() { if (activeMode === 'tracking') { stopTracking(); this.innerText = "🧭 Start Tracking"; this.style.background = ""; } else { activeMode = 'tracking'; currentCoords = []; this.innerText = "🛑 Stop Tracking"; this.style.background = "#d32f2f"; trackWatchId = navigator.geolocation.watchPosition(pos => { const coord = [pos.coords.longitude, pos.coords.latitude]; currentCoords.push(coord); map.setCenter(coord); updatePreview(); }, null, { enableHighAccuracy: true }); } closePanel(); }); function stopTracking() { navigator.geolocation.clearWatch(trackWatchId); if (currentCoords.length > 1) { saveFeature(turf.lineString(currentCoords, { name: "Track " + new Date().toLocaleTimeString() })); } exitMode(); } /* --- 9. PENGELOLAAN DATA (SAVE & GALLERY) --- */ function saveFeature(feature) { surveyGeoJSON.features.push(feature); map.getSource('survey-data').setData(surveyGeoJSON); plotGallery.push(feature); updateGallery(); } function updateGallery() { const container = document.getElementById('galleryContainer'); container.innerHTML = plotGallery.map(f => `
📦 ${f.properties.name || 'Unnamed'}
`).join(''); } function exitMode() { activeMode = null; currentCoords = []; document.getElementById('drawControls').style.display = 'none'; document.getElementById('measureInfo').style.display = 'none'; map.getSource('survey-data').setData(surveyGeoJSON); // Reset view ke data tersimpan } document.getElementById('btnFinishAction').addEventListener('click', () => { if (activeMode === 'polygon' && currentCoords.length > 2) { const name = prompt("Nama Polygon:", "Area " + plotGallery.length); saveFeature(turf.polygon([[...currentCoords, currentCoords[0]]], { name })); } exitMode(); }); document.getElementById('btnCancelAction').addEventListener('click', exitMode); function updateMeasureLabel(val, type) { const el = document.getElementById('measureInfo'); if (type === 'length') el.innerText = `Jarak: ${val.toFixed(3)} km | ${(val*1000).toFixed(0)} m`; else el.innerText = `Luas: ${(val/10000).toFixed(2)} Ha | ${(val/1000000).toFixed(3)} km²`; } /* --- 10. ADVANCED SYMBOLOGY & UI COMPONENTS --- */ const symStyle = ` `; document.head.insertAdjacentHTML('beforeend', symStyle); const symHTML = `
Simbologi & Labeling
Hollow (Tanpa Isian)
Warna Isian:
Warna Garis:
Ketebalan Garis:
Pilih Field Label:
Tanpa Label
TERAPKAN GAYA
TUTUP
━ TABEL ATRIBUT ━
`; document.body.insertAdjacentHTML('beforeend', symHTML); /* --- 11. IMPORT SHP & TABEL ATRIBUT --- */ document.getElementById('btnImportSHP').addEventListener('click', () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.zip'; input.onchange = async (e) => { const file = e.target.files[0]; if (!file) return; try { const buffer = await file.arrayBuffer(); const geojson = await shp(buffer); const features = Array.isArray(geojson) ? geojson[0].features : geojson.features; surveyGeoJSON.features.push(...features); map.getSource('survey-data').setData(surveyGeoJSON); const fields = Object.keys(features[0].properties); document.getElementById('labelFieldSelect').innerHTML = '
Tanpa Label
' + fields.map(f => `
${f}
`).join(''); const bbox = turf.bbox({type: 'FeatureCollection', features: features}); map.fitBounds([[bbox[0], bbox[1]], [bbox[2], bbox[3]]], {padding: 50}); buildAttributeTable(features); alert("SHP Berhasil Dimuat!"); } catch (err) { alert("Error: Pastikan ZIP berisi file .shp, .dbf, dll."); } }; input.click(); closePanel(); }); function buildAttributeTable(features) { const container = document.getElementById('attrTableBody'); if (!features || features.length === 0) return; let html = `
`; const keys = Object.keys(features[0].properties); keys.forEach(k => html += `
${k}
`); html += `
`; features.forEach(f => { html += `
`; keys.forEach(k => html += `
${f.properties[k] || ''}
`); html += `
`; }); html += `
`; container.innerHTML = html; } document.getElementById('btnAttrTable').addEventListener('click', () => { document.getElementById('attrWrap').classList.toggle('active'); closePanel(); }); /* --- 12. APPLY SYMBOLOGY & EXPORT KML --- */ document.getElementById('applySymBtn').addEventListener('click', () => { const hollow = document.getElementById('checkHollow').checked; const fill = document.getElementById('colorFill').value; const line = document.getElementById('colorLine').value; const width = parseFloat(document.getElementById('widthLine').value); const labelField = document.getElementById('labelFieldSelect').value; map.setPaintProperty('survey-fill', 'fill-color', fill); map.setPaintProperty('survey-fill', 'fill-opacity', hollow ? 0 : 0.4); map.setPaintProperty('survey-line', 'line-color', line); map.setPaintProperty('survey-line', 'line-width', width); if (labelField) { if (!map.getLayer('survey-labels')) { map.addLayer({ 'id': 'survey-labels', 'type': 'symbol', 'source': 'survey-data', 'layout': { 'text-field': ['get', labelField], 'text-size': 12, 'text-variable-anchor': ['top'], 'text-radial-offset': 0.5 }, 'paint': { 'text-color': '#fff', 'text-halo-color': '#000', 'text-halo-width': 1 } }); } else { map.setLayoutProperty('survey-labels', 'text-field', ['get', labelField]); } } }); document.getElementById('btnExportKML').addEventListener('click', () => { if (surveyGeoJSON.features.length === 0) return alert("Belum ada data!"); let kml = `
`; surveyGeoJSON.features.forEach(f => { kml += `
${f.properties.name || 'Feature'}
`; if (f.geometry.type === 'Point') { kml += `
${f.geometry.coordinates.join(',')}
`; } else if (f.geometry.type === 'Polygon') { const coords = f.geometry.coordinates[0].map(c => c.join(',')).join(' '); kml += `
${coords}
`; } else if (f.geometry.type === 'LineString') { const coords = f.geometry.coordinates.map(c => c.join(',')).join(' '); kml += `
${coords}
`; } kml += `
`; }); kml += `
`; const blob = new Blob([kml], {type: "application/vnd.google-earth.kml+xml"}); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = "Survey_Export.kml"; a.click(); });