// =============================== // MAPPA GLOBALE (marker personalizzati + bottom sheet + cluster intelligenti) // =============================== document.getElementById("openMapBtn").addEventListener("click", openGlobalMap); function openGlobalMap() { const mapDiv = document.getElementById("globalMap"); const gallery = document.getElementById("gallery"); const isOpen = mapDiv.classList.contains("open"); // Toggle mappa if (isOpen) { mapDiv.classList.remove("open"); gallery.classList.remove("hidden"); closeBottomSheet(); return; } mapDiv.classList.add("open"); gallery.classList.add("hidden"); // Inizializza solo la prima volta if (!globalMap) { globalMap = L.map("globalMap").setView([42.5, 12.5], 6); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19 }).addTo(globalMap); // =============================== // FUNZIONE: calcola luminosità miniatura // =============================== function getBrightness(photo) { return new Promise(resolve => { const img = new Image(); img.crossOrigin = "anonymous"; img.src = `https://prova.patachina.it/${photo.thub1}`; img.onload = () => { const canvas = document.createElement("canvas"); canvas.width = 20; canvas.height = 20; const ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, 20, 20); const data = ctx.getImageData(0, 0, 20, 20).data; let total = 0; for (let i = 0; i < data.length; i += 4) { total += (data[i] + data[i + 1] + data[i + 2]) / 3; } resolve(total / (20 * 20)); }; img.onerror = () => resolve(0); }); } // =============================== // FUNZIONE: sceglie la foto migliore (recenti + luminosa) // =============================== async function chooseBestRepresentative(photos) { // Ordina per data photos.sort((a, b) => new Date(b.taken_at) - new Date(a.taken_at)); // Prendi le 3 più recenti const candidates = photos.slice(0, 3); // Calcola luminosità const brightnessValues = await Promise.all( candidates.map(p => getBrightness(p)) ); // Trova la più luminosa let bestIndex = 0; let bestValue = brightnessValues[0]; for (let i = 1; i < brightnessValues.length; i++) { if (brightnessValues[i] > bestValue) { bestValue = brightnessValues[i]; bestIndex = i; } } return candidates[bestIndex]; } // =============================== // CLUSTER PERSONALIZZATI // =============================== globalMarkers = L.markerClusterGroup({ iconCreateFunction: function (cluster) { const markers = cluster.getAllChildMarkers(); const photos = markers.map(m => m.photoData); // Mostra SUBITO la più recente (velocissimo) photos.sort((a, b) => new Date(b.taken_at) - new Date(a.taken_at)); const representative = photos[0]; // Aggiorna in background con la più luminosa chooseBestRepresentative(photos).then(best => { const icon = cluster._icon; if (!icon) return; const back = icon.querySelector(".cluster-back"); const front = icon.querySelector(".cluster-front"); if (back) back.src = `https://prova.patachina.it/${best.thub1}`; if (front) front.src = `https://prova.patachina.it/${best.thub1}`; }); return L.divIcon({ html: `
`, className: "", iconSize: [56, 56] }); } }); globalMap.addLayer(globalMarkers); // =============================== // CLICK SUI CLUSTER → BOTTOM SHEET // =============================== globalMarkers.on("clusterclick", function (a) { const markers = a.layer.getAllChildMarkers(); const photos = markers.map(m => m.photoData); openBottomSheet(photos); }); // =============================== // MARKER SINGOLI PERSONALIZZATI // =============================== photosData.forEach(photo => { if (!photo.gps || !photo.gps.lat || !photo.gps.lng) return; const markerIcon = L.divIcon({ html: `
`, className: "", iconSize: [48, 48] }); const marker = L.marker([photo.gps.lat, photo.gps.lng], { icon: markerIcon }); marker.photoData = photo; marker.on("click", () => { openBottomSheet([photo]); }); globalMarkers.addLayer(marker); }); } // Fix dimensioni mappa setTimeout(() => globalMap.invalidateSize(), 200); }