// ============================================================ // feature-basemap.js // Layer referensi statis dari GeoJSON lokal: // - Batas Kecamatan Kota Pontianak (Admin_Kecamatan) // - Jaringan Jalan (Jaringan_Jalan) // - Sungai Besar (Sungai_Besar) // ============================================================ const basemapCfg = { kecamatan: { label: 'Batas Kecamatan', file: 'assets/map/Admin_Kecamatan.geojson', color: '#7c3aed', fillColor: '#7c3aed', fillOpacity: 0.08, weight: 2.5, icon: '🏙️', popupProp: ['KECAMATAN', 'KELURAHAN', 'KODE_KEC', 'LUAS_HA'], popupLabel: { KECAMATAN: 'Kecamatan', KELURAHAN: 'Kelurahan', KODE_KEC: 'Kode', LUAS_HA: 'Luas (ha)' } }, jalan: { label: 'Jaringan Jalan', file: 'assets/map/Jaringan_Jalan.geojson', color: '#d97706', weight: 1.8, fillOpacity: 0, icon: '🛤️', popupProp: ['NAMOBJ', 'REMARK', 'FCODE'], popupLabel: { NAMOBJ: 'Nama', REMARK: 'Keterangan', FCODE: 'Kode' } }, sungai: { label: 'Sungai Besar', file: 'assets/map/Sungai_Besar.geojson', color: '#0ea5e9', fillColor: '#0ea5e9', fillOpacity: 0.25, weight: 1.5, icon: '🌊', popupProp: ['NAMOBJ', 'REMARK', 'FCODE'], popupLabel: { NAMOBJ: 'Nama', REMARK: 'Keterangan', FCODE: 'Kode' } } }; // Cache untuk data GeoJSON yang sudah di-fetch agar tidak fetch ulang const _basemapCache = {}; /** * Fetch GeoJSON dan buat Leaflet GeoJSON layer dengan style + popup. */ async function loadBasemapLayer(key) { const cfg = basemapCfg[key]; const layerKey = 'basemap_' + key; // Jika layer sudah ada isinya, tidak perlu reload let hasLayers = false; layers[layerKey].eachLayer(() => { hasLayers = true; }); if (hasLayers) return; try { // Gunakan cache jika sudah pernah di-fetch let geojsonData = _basemapCache[key]; if (!geojsonData) { const resp = await fetch(cfg.file); if (!resp.ok) throw new Error(`HTTP ${resp.status}`); geojsonData = await resp.json(); _basemapCache[key] = geojsonData; } const styleOpts = { color: cfg.color, weight: cfg.weight, fillOpacity: cfg.fillOpacity ?? 0, fillColor: cfg.fillColor || cfg.color, opacity: 0.9 }; const geoLayer = L.geoJSON(geojsonData, { style: styleOpts, pointToLayer: (feature, latlng) => L.circleMarker(latlng, { radius: 5, ...styleOpts }), onEachFeature: (feature, layer) => { const props = feature.properties || {}; // Cari nama property (case-insensitive fallback) const findVal = (keys) => { for (const k of keys) { const found = Object.keys(props).find(p => p.toUpperCase() === k.toUpperCase()); if (found && props[found]) return props[found]; } return null; }; const rows = cfg.popupProp .map(p => { const found = Object.keys(props).find(k => k.toUpperCase() === p.toUpperCase()); const val = found ? props[found] : null; if (!val) return ''; return `
${cfg.popupLabel[p] || p}: ${val}
`; }) .filter(Boolean) .join(''); const nameKeys = ['NAMOBJ', 'NAMA', 'NAME', 'KECAMATAN', 'KELURAHAN']; const title = findVal(nameKeys) || cfg.label; if (rows) { layer.bindPopup(`