Files
WebGIS_PovertyMap/Leaflet/assets/js/kecamatan-layer.js
T

156 lines
4.2 KiB
JavaScript

(function () {
'use strict';
const DEFAULT_SOURCE = 'assets/data/Kecamatan.json';
const DEFAULT_ANCHOR = {
lat: -0.06054796552220232,
lng: 109.34490231930592
};
const DEFAULT_GEO_BOUNDS = {
south: -0.0981948,
west: 109.2741676,
north: 0.0381168,
east: 109.3853475
};
const DEFAULT_CALIBRATION = {
scaleX: 1,
scaleY: 1,
offsetLat: 0,
offsetLng: 0
};
function walkCoordinates(coordinates, callback) {
if (!Array.isArray(coordinates)) {
return;
}
if (coordinates.length >= 2 && typeof coordinates[0] === 'number' && typeof coordinates[1] === 'number') {
callback(coordinates[0], coordinates[1]);
return;
}
coordinates.forEach((child) => walkCoordinates(child, callback));
}
function getCoordinateBounds(data) {
const bounds = {
minX: Infinity,
minY: Infinity,
maxX: -Infinity,
maxY: -Infinity
};
function addGeometry(geometry) {
if (!geometry) {
return;
}
if (geometry.type === 'GeometryCollection') {
(geometry.geometries || []).forEach(addGeometry);
return;
}
walkCoordinates(geometry.coordinates, (x, y) => {
bounds.minX = Math.min(bounds.minX, x);
bounds.minY = Math.min(bounds.minY, y);
bounds.maxX = Math.max(bounds.maxX, x);
bounds.maxY = Math.max(bounds.maxY, y);
});
}
if (data.type === 'FeatureCollection') {
(data.features || []).forEach((feature) => addGeometry(feature.geometry));
} else if (data.type === 'Feature') {
addGeometry(data.geometry);
} else {
addGeometry(data);
}
if (!Number.isFinite(bounds.minX) || !Number.isFinite(bounds.minY)) {
return null;
}
return bounds;
}
function createBoundingBoxTransform(sourceBounds, targetBounds, calibration) {
const sourceWidth = sourceBounds.maxX - sourceBounds.minX;
const sourceHeight = sourceBounds.maxY - sourceBounds.minY;
const targetCenterLng = (targetBounds.west + targetBounds.east) / 2 + calibration.offsetLng;
const targetCenterLat = (targetBounds.south + targetBounds.north) / 2 + calibration.offsetLat;
const targetWidth = (targetBounds.east - targetBounds.west) * calibration.scaleX;
const targetHeight = (targetBounds.north - targetBounds.south) * calibration.scaleY;
return function coordsToLatLng(coordinates) {
const xRatio = ((coordinates[0] - sourceBounds.minX) / sourceWidth) - 0.5;
const yRatio = ((coordinates[1] - sourceBounds.minY) / sourceHeight) - 0.5;
const lng = targetCenterLng + (xRatio * targetWidth);
const lat = targetCenterLat + (yRatio * targetHeight);
return L.latLng(lat, lng);
};
}
window.addKecamatanLayer = async function addKecamatanLayer(map, options) {
const settings = Object.assign({
source: DEFAULT_SOURCE,
anchor: DEFAULT_ANCHOR,
targetBounds: DEFAULT_GEO_BOUNDS,
calibration: DEFAULT_CALIBRATION,
fitBounds: false
}, options || {});
if (!map || typeof L === 'undefined') {
return null;
}
if (!map.getPane('kecamatanPane')) {
map.createPane('kecamatanPane');
map.getPane('kecamatanPane').style.zIndex = 350;
}
const response = await fetch(settings.source, {
headers: { 'Accept': 'application/json' }
});
if (!response.ok) {
throw new Error('Gagal memuat data batas kecamatan.');
}
const data = await response.json();
const coordinateBounds = getCoordinateBounds(data);
if (!coordinateBounds) {
throw new Error('Data batas kecamatan tidak memiliki koordinat valid.');
}
const layer = L.geoJSON(data, {
coordsToLatLng: createBoundingBoxTransform(coordinateBounds, settings.targetBounds, settings.calibration),
pane: 'kecamatanPane',
style: {
color: '#0f766e',
weight: 2,
opacity: 0.9,
fillColor: '#14b8a6',
fillOpacity: 0.08,
dashArray: '6 4'
},
onEachFeature: function (feature, featureLayer) {
const name = feature && feature.properties && (
feature.properties.nama ||
feature.properties.NAMA ||
feature.properties.KECAMATAN ||
feature.properties.kecamatan
);
featureLayer.bindPopup(name ? `Kecamatan: ${name}` : 'Batas Kecamatan');
}
}).addTo(map);
if (settings.fitBounds && layer.getBounds().isValid()) {
map.fitBounds(layer.getBounds().pad(0.12), { maxZoom: 15 });
}
return layer;
};
}());