// public/js/map/photos/photoMarkers.js // =================================== // MAPBOX PHOTO MARKERS // =================================== (() => { "use strict"; let mapboxMap = null; const markers = new Map(); const SOURCE_ID = "photos"; // =================================== // SET MAP // =================================== function setMap(map) { mapboxMap = map; console.log("[PhotoMarkers] setMap"); } // =================================== // CREA ELEMENTO FOTO // =================================== function createPhotoElement(feature) { const img = document.createElement("img"); img.src = feature.properties?.thumb || ""; img.width = 46; img.height = 46; img.style.borderRadius = "7px"; img.style.objectFit = "cover"; img.style.border = "2px solid white"; img.style.cursor = "pointer"; return img; } // =================================== // CLICK FOTO // =================================== function handlePhotoClick(feature) { if (!feature) { return; } const id = String( feature.properties?.id, ); // ================================= // FOTO VICINE // ================================= if ( window.MapboxPhotoSpiderfy ) { const nearbyPhotos = window.MapboxPhotoSpiderfy.getNearbyPhotos( feature, 3, ); console.log( "[PhotoMarkers] foto entro 3 metri:", nearbyPhotos.length, ); if (nearbyPhotos.length > 1) { window.MapboxPhotoSpiderfy.spiderfyPhotos( nearbyPhotos, ); return; } } // ================================= // APERTURA FOTO // ================================= const items = typeof window.getLocalItems === "function" ? window.getLocalItems() : []; const item = items.find( (photo) => String(photo.id) === id, ); if (item) { window.openPhotoMapItem?.( item, ); } // ================================= // CHIUDI EVENTUALE SPIDERFY // ================================= if ( window.MapboxPhotoSpiderfy ) { window.MapboxPhotoSpiderfy.clear(); } } // =================================== // CREA MARKER // =================================== function createMarker(feature) { if (!mapboxMap) { return null; } const id = String( feature.properties?.id, ); const img = createPhotoElement(feature); img.addEventListener( "click", (event) => { event.stopPropagation(); handlePhotoClick(feature); }, ); const marker = new mapboxgl.Marker({ element: img, }) .setLngLat( feature.geometry.coordinates, ) .addTo(mapboxMap); marker.__originalLngLat = feature.geometry.coordinates; marker.__spider = false; marker.__photoId = id; markers.set(id, marker); return marker; } // =================================== // FOTO VISIBILI // =================================== function getVisibleIds() { if (!mapboxMap) { return new Set(); } if ( !mapboxMap.getSource( SOURCE_ID, ) ) { return new Set(); } const sourcePoints = mapboxMap.querySourceFeatures( SOURCE_ID, { filter: [ "!", ["has", "point_count"], ], }, ); return new Set( sourcePoints.map( (feature) => String( feature.properties?.id, ), ), ); } // =================================== // UPDATE // =================================== function update(features = []) { if (!mapboxMap) { return; } const visibleIds = getVisibleIds(); console.log( "[PhotoMarkers] visibility", { features: features.length, visible: visibleIds.size, }, ); // ================================= // RIMUOVI MARKER CLUSTERIZZATI // ================================= for ( const [ id, marker, ] of markers ) { if ( !visibleIds.has(id) ) { // Lo spiderfy deve rimanere // indipendente dai marker normali. if (!marker.__spider) { marker.remove(); markers.delete(id); } } } // ================================= // CREA / AGGIORNA FOTO // ================================= for (const feature of features) { const id = String( feature.properties?.id, ); // -------------------------------- // LA FOTO È DENTRO UN CLUSTER // -------------------------------- if ( !visibleIds.has(id) ) { continue; } // -------------------------------- // MARKER ESISTENTE // -------------------------------- if ( markers.has(id) ) { const marker = markers.get(id); if ( !marker.__spider ) { marker.setLngLat( feature.geometry.coordinates, ); } marker.__originalLngLat = feature.geometry.coordinates; continue; } // -------------------------------- // CREA MARKER // -------------------------------- createMarker(feature); } // ================================= // RIMOZIONE FINALE // ================================= for ( const [ id, marker, ] of markers ) { if ( marker.__spider ) { continue; } if ( !visibleIds.has( String(id), ) ) { marker.remove(); markers.delete(id); } } } // =================================== // GET MARKER // =================================== function get(id) { return markers.get( String(id), ); } // =================================== // GET ALL // =================================== function getAll() { return markers; } // =================================== // ADD SPIDER MARKER // =================================== function addSpiderMarker( id, marker, ) { markers.set( String(id), marker, ); } // =================================== // REMOVE // =================================== function remove(id) { const key = String(id); const marker = markers.get(key); if (!marker) { return; } marker.remove(); markers.delete(key); } // =================================== // CLEAR // =================================== function clear() { for ( const marker of markers.values() ) { marker.remove(); } markers.clear(); } // =================================== // SIZE // =================================== function size() { return markers.size; } // =================================== // DEBUG // =================================== function debug() { console.log( "[PhotoMarkers] debug", { markers: markers.size, ids: [...markers.keys()], }, ); } // =================================== // API PUBBLICA // =================================== window.MapboxPhotoMarkers = { setMap, update, createMarker, getVisibleIds, get, getAll, addSpiderMarker, remove, clear, size, debug, }; })();