Files
termanager2/resources/js/piantine.js

144 lines
5.2 KiB
JavaScript

// Editor delle piantine (pagina /piantine, solo amministratore).
//
// Mappa Leaflet su tessere OpenStreetMap: mostra l'area del KML, i poligoni
// dei territori già salvati e permette di disegnarne di nuovi con
// leaflet-draw. Parla con il componente Livewire attraverso eventi:
// JS → Livewire: 'poligono-disegnato', 'territorio-selezionato-mappa'
// Livewire → JS: 'piantine-dati-aggiornati'
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet-draw';
import 'leaflet-draw/dist/leaflet.draw.css';
const STILE_AREA = { color: '#2563eb', weight: 2, dashArray: '8 6', fill: false, interactive: false };
const STILE_SALVATO = { color: '#6b7280', weight: 2, fillColor: '#6b7280', fillOpacity: 0.12 };
const STILE_SELEZIONATO = { color: '#4f46e5', weight: 3, fillColor: '#6366f1', fillOpacity: 0.2 };
const STILE_IN_ATTESA = { color: '#d81b1b', weight: 3, fillColor: '#ef4444', fillOpacity: 0.15 };
function initPiantine() {
const contenitore = document.getElementById('piantine-map');
if (!contenitore || contenitore.dataset.inizializzato) {
return;
}
contenitore.dataset.inizializzato = '1';
let dati = { area: null, poligoni: [], selezionato: null };
try {
dati = JSON.parse(document.getElementById('piantine-dati').textContent);
} catch {
// si parte comunque con la mappa vuota
}
// Etichette in italiano per la barra di disegno.
L.drawLocal.draw.toolbar.buttons.polygon = 'Disegna il poligono di un territorio';
L.drawLocal.draw.toolbar.actions = { title: 'Annulla il disegno', text: 'Annulla' };
L.drawLocal.draw.toolbar.finish = { title: 'Concludi il disegno', text: 'Concludi' };
L.drawLocal.draw.toolbar.undo = { title: 'Rimuovi l\'ultimo punto', text: 'Ultimo punto' };
L.drawLocal.draw.handlers.polygon.tooltip = {
start: 'Clicca sulla mappa per iniziare il poligono.',
cont: 'Continua a cliccare lungo il confine.',
end: 'Clicca sul primo punto per chiudere il poligono.',
};
const mappa = L.map(contenitore, { zoomControl: true });
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(mappa);
let layerArea = null;
const layerSalvati = L.featureGroup().addTo(mappa);
let layerInAttesa = null;
mappa.addControl(new L.Control.Draw({
draw: {
polygon: { allowIntersection: false, showArea: false, shapeOptions: STILE_IN_ATTESA },
polyline: false,
rectangle: false,
circle: false,
circlemarker: false,
marker: false,
},
edit: false,
}));
function ridisegna(nuoviDati, adattaVista) {
dati = nuoviDati;
if (layerArea) {
mappa.removeLayer(layerArea);
layerArea = null;
}
if (dati.area) {
layerArea = L.geoJSON(dati.area, { style: STILE_AREA, interactive: false }).addTo(mappa);
}
layerSalvati.clearLayers();
for (const poligono of dati.poligoni) {
const selezionato = dati.selezionato === poligono.territorioId;
const layer = L.geoJSON(
{ type: 'Feature', properties: {}, geometry: poligono.geometry },
{ style: selezionato ? STILE_SELEZIONATO : STILE_SALVATO }
);
layer.bindTooltip(`Terr. ${poligono.numero}`, { sticky: true });
layer.on('click', () => {
window.Livewire.dispatch('territorio-selezionato-mappa', { territorioId: poligono.territorioId });
});
layerSalvati.addLayer(layer);
}
if (!adattaVista) {
return;
}
const riferimento = layerArea ?? (dati.poligoni.length ? layerSalvati : null);
if (riferimento) {
mappa.fitBounds(riferimento.getBounds().pad(0.08));
} else {
mappa.setView([41.9, 12.5], 6); // Italia: nessun dato ancora caricato
}
}
ridisegna(dati, true);
mappa.on(L.Draw.Event.CREATED, (evento) => {
if (layerInAttesa) {
mappa.removeLayer(layerInAttesa);
}
layerInAttesa = evento.layer;
layerInAttesa.setStyle(STILE_IN_ATTESA);
layerInAttesa.addTo(mappa);
window.Livewire.dispatch('poligono-disegnato', { geometry: evento.layer.toGeoJSON().geometry });
});
let registrato = false;
document.addEventListener('livewire:init', registraEventi);
if (window.Livewire) {
registraEventi();
}
function registraEventi() {
if (registrato) {
return;
}
registrato = true;
window.Livewire.on('piantine-dati-aggiornati', ({ dati: nuovi }) => {
// Dopo un salvataggio il poligono provvisorio è diventato
// definitivo (o è stato scartato): via il tracciato rosso.
if (layerInAttesa) {
mappa.removeLayer(layerInAttesa);
layerInAttesa = null;
}
ridisegna(nuovi, false);
});
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initPiantine);
} else {
initPiantine();
}