204 lines
No EOL
5.5 KiB
JavaScript
204 lines
No EOL
5.5 KiB
JavaScript
// ===============================
|
|
// MAPPA GLOBALE — stile Google Photos Web
|
|
// ===============================
|
|
|
|
window.globalMap = null;
|
|
window.globalMarkers = null;
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const openBtn = document.getElementById("openMapBtn");
|
|
if (!openBtn) return;
|
|
|
|
openBtn.addEventListener("click", openGlobalMap);
|
|
|
|
const RADIUS_PX = 50;
|
|
const DISABLE_CLUSTER_AT_ZOOM = 18;
|
|
const OPEN_STRIP_CHILDREN_MAX = 20;
|
|
|
|
// ===============================
|
|
// APRI / CHIUDI MAPPA
|
|
// ===============================
|
|
async function openGlobalMap() {
|
|
const mapDiv = document.getElementById("globalMap");
|
|
const gallery = document.getElementById("gallery");
|
|
if (!mapDiv) return;
|
|
|
|
const isOpen = mapDiv.classList.contains("open");
|
|
|
|
if (isOpen) {
|
|
mapDiv.classList.remove("open");
|
|
gallery?.classList.remove("hidden");
|
|
window.closeBottomSheet?.();
|
|
return;
|
|
}
|
|
|
|
mapDiv.classList.add("open");
|
|
gallery?.classList.add("hidden");
|
|
|
|
await new Promise(r => requestAnimationFrame(r));
|
|
|
|
if (!window.globalMap) initMap();
|
|
else window.globalMap.invalidateSize();
|
|
|
|
redrawPhotoMarkers();
|
|
}
|
|
|
|
// ===============================
|
|
// INIZIALIZZA MAPPA
|
|
// ===============================
|
|
function initMap() {
|
|
console.log("Inizializzo mappa Leaflet + MarkerCluster…");
|
|
|
|
window.globalMap = L.map("globalMap", {
|
|
zoomControl: true,
|
|
attributionControl: true
|
|
}).setView([42.5, 12.5], 6);
|
|
|
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
|
maxZoom: 19
|
|
}).addTo(window.globalMap);
|
|
|
|
window.globalMarkers = L.markerClusterGroup({
|
|
showCoverageOnHover: false,
|
|
spiderfyOnMaxZoom: true,
|
|
disableClusteringAtZoom: DISABLE_CLUSTER_AT_ZOOM,
|
|
iconCreateFunction: clusterIconRenderer
|
|
});
|
|
|
|
window.globalMarkers.on("clusterclick", onClusterClick);
|
|
|
|
window.globalMap.addLayer(window.globalMarkers);
|
|
}
|
|
|
|
// ===============================
|
|
// RENDER CLUSTER
|
|
// ===============================
|
|
function clusterIconRenderer(cluster) {
|
|
const count = cluster.getChildCount();
|
|
const size = Math.min(92, Math.round(28 + Math.sqrt(count) * 6));
|
|
const cls = count > 200 ? "cluster-xl" :
|
|
count > 50 ? "cluster-lg" :
|
|
count > 10 ? "cluster-md" : "cluster-sm";
|
|
|
|
const children = cluster.getAllChildMarkers().slice(0, 4);
|
|
const thumbs = children
|
|
.map(m => m.__photo?.thub2 || m.__photo?.thub1)
|
|
.filter(Boolean)
|
|
.map(t => toAbsoluteUrl(t, children[0].__photo.name, "thumbs", children[0].__photo.cartella));
|
|
|
|
const collage = thumbs.length
|
|
? `<div class="cluster-collage">${thumbs.map((t,i)=>`<div class="c${i}"><img src="${t}"></div>`).join("")}</div>`
|
|
: "";
|
|
|
|
return L.divIcon({
|
|
html: `
|
|
<div class="gp-cluster ${cls}" style="width:${size}px;height:${size}px;">
|
|
${collage}
|
|
<div class="gp-count"><span>${count}</span></div>
|
|
</div>`,
|
|
className: "marker-cluster-wrapper",
|
|
iconSize: L.point(size, size)
|
|
});
|
|
}
|
|
|
|
// ===============================
|
|
// CLICK SU CLUSTER
|
|
// ===============================
|
|
function onClusterClick(a) {
|
|
const markers = a.layer.getAllChildMarkers();
|
|
const count = markers.length;
|
|
|
|
if (count <= OPEN_STRIP_CHILDREN_MAX ||
|
|
window.globalMap.getZoom() >= DISABLE_CLUSTER_AT_ZOOM - 1) {
|
|
|
|
const photos = markers.map(m => m.__photo).filter(Boolean);
|
|
|
|
if (photos.length > 1) window.openBottomSheet?.(photos);
|
|
else if (photos.length === 1) openPhotoModal(photos[0]);
|
|
|
|
} else {
|
|
window.globalMap.fitBounds(a.layer.getBounds(), {
|
|
padding: [60, 60],
|
|
maxZoom: DISABLE_CLUSTER_AT_ZOOM,
|
|
animate: true
|
|
});
|
|
}
|
|
}
|
|
|
|
// ===============================
|
|
// ICONA FOTO
|
|
// ===============================
|
|
function createPhotoIcon(photo) {
|
|
const thumb = toAbsoluteUrl(
|
|
photo.thub2 || photo.thub1,
|
|
photo.name,
|
|
"thumbs",
|
|
photo.cartella
|
|
);
|
|
|
|
return L.icon({
|
|
iconUrl: thumb,
|
|
iconSize: [56, 56],
|
|
iconAnchor: [28, 28],
|
|
className: "photo-marker"
|
|
});
|
|
}
|
|
|
|
// ===============================
|
|
// APRI MODAL FOTO
|
|
// ===============================
|
|
function openPhotoModal(photo) {
|
|
const thumb = toAbsoluteUrl(
|
|
photo.thub2 || photo.thub1 || photo.path,
|
|
photo.name,
|
|
"thumbs",
|
|
photo.cartella
|
|
);
|
|
|
|
const original = toAbsoluteUrl(
|
|
photo.path,
|
|
photo.name,
|
|
"original",
|
|
photo.cartella
|
|
);
|
|
|
|
window.closeBottomSheet?.();
|
|
window.openModal?.(original, thumb, photo);
|
|
}
|
|
|
|
// ===============================
|
|
// REDRAW MARKERS
|
|
// ===============================
|
|
function redrawPhotoMarkers() {
|
|
if (!window.globalMarkers) return;
|
|
|
|
window.globalMarkers.clearLayers();
|
|
|
|
const photos = getLocalPhotos();
|
|
photos.forEach(photo => {
|
|
const lat = +photo?.gps?.lat;
|
|
const lng = +photo?.gps?.lng;
|
|
if (!lat || !lng) return;
|
|
|
|
const marker = L.marker([lat, lng], {
|
|
icon: createPhotoIcon(photo),
|
|
title: photo.name || ""
|
|
});
|
|
|
|
marker.__photo = photo;
|
|
|
|
marker.on("click", () => openPhotoModal(photo));
|
|
|
|
window.globalMarkers.addLayer(marker);
|
|
});
|
|
}
|
|
|
|
// ===============================
|
|
// AGGANCIA REFRESH GALLERY
|
|
// ===============================
|
|
const originalRefresh = window.refreshGallery;
|
|
window.refreshGallery = function (...args) {
|
|
originalRefresh?.apply(this, args);
|
|
redrawPhotoMarkers();
|
|
};
|
|
}); |