server_photo_s85js/public/js/map/mapboxMarkers.js
2026-08-11 08:45:04 +02:00

777 lines
14 KiB
JavaScript

// public/js/map/mapboxMarkers.js
// ===================================
// MAPBOX MARKERS CONTROLLER
// ===================================
(() => {
"use strict";
let mapboxMap = null;
// ===================================
// STATO
// ===================================
const state = {
photos: [],
activities: [],
routes: [],
};
let mapEventsInitialized = false;
let mapEventsMap = null;
// ===================================
// MAPPA
// ===================================
function setMap(map) {
if (!map) {
console.error(
"[MapboxMarkers] mappa non valida",
);
return;
}
// ---------------------------------
// STESSA MAPPA
// ---------------------------------
if (mapboxMap === map) {
console.log(
"[MapboxMarkers] stessa mappa già collegata",
);
initializeModules();
refreshAll();
return;
}
// ---------------------------------
// NUOVA MAPPA
// ---------------------------------
mapboxMap = map;
console.log(
"[MapboxMarkers] mappa collegata",
);
// =================================
// PHOTOS
// =================================
if (window.PhotoSource) {
console.log(
"[MapboxMarkers] PhotoSource collegato",
);
}
if (window.MapboxPhotoClusters) {
window.MapboxPhotoClusters.setMap(
mapboxMap,
);
}
if (window.MapboxPhotoMarkers) {
window.MapboxPhotoMarkers.setMap(
mapboxMap,
);
}
if (window.MapboxPhotoSpiderfy) {
window.MapboxPhotoSpiderfy.setMap(
mapboxMap,
);
}
// =================================
// ACTIVITIES
// =================================
if (window.ActivitySource) {
console.log(
"[MapboxMarkers] ActivitySource collegato",
);
}
if (window.MapboxActivityClusters) {
window.MapboxActivityClusters.setMap(
mapboxMap,
);
}
if (window.MapboxActivityMarkers) {
window.MapboxActivityMarkers.setMap(
mapboxMap,
);
}
// =================================
// EVENTI
// =================================
setupMapEvents();
// =================================
// INIZIALIZZAZIONE
// =================================
initializeModules();
// =================================
// RIPRISTINO DATI
// =================================
refreshAll();
}
// ===================================
// INIZIALIZZAZIONE MODULI
// ===================================
function initializeModules() {
if (!mapboxMap) {
return;
}
if (!mapboxMap.isStyleLoaded()) {
return;
}
// =================================
// PHOTOS SOURCE
// =================================
if (window.PhotoSource) {
window.PhotoSource.update(
mapboxMap,
state.photos,
);
}
// =================================
// PHOTOS CLUSTER
// =================================
if (window.MapboxPhotoClusters) {
//window.MapboxPhotoClusters.createLayer();
}
// =================================
// ACTIVITIES SOURCE
// =================================
if (window.ActivitySource) {
window.ActivitySource.update(
mapboxMap,
state.activities,
);
}
// =================================
// ACTIVITIES CLUSTER
// =================================
if (window.MapboxActivityClusters) {
window.MapboxActivityClusters.createLayer();
}
}
// ===================================
// EVENTI MAPPA
// ===================================
function setupMapEvents() {
if (!mapboxMap) {
return;
}
if (mapEventsInitialized) {
return;
}
mapEventsInitialized = true;
// =================================
// HELPER REFRESH MAPBOX MARKERS
// =================================
function refreshMapboxMarkers(reason) {
if (!mapboxMap) {
return;
}
if (!mapboxMap.isStyleLoaded()) {
return;
}
console.log(
`[MapboxMarkers] refreshMapboxMarkers → ${reason}`,
);
// ---------------------------------
// PHOTO CLUSTERS
// ---------------------------------
if (window.MapboxPhotoClusters) {
window.MapboxPhotoClusters.createLayer();
window.MapboxPhotoClusters.update();
}
// ---------------------------------
// PHOTO MARKERS
// ---------------------------------
if (window.MapboxPhotoMarkers) {
window.MapboxPhotoMarkers.update(
state.photos,
);
}
// ---------------------------------
// ACTIVITY CLUSTERS
// ---------------------------------
if (window.MapboxActivityClusters) {
window.MapboxActivityClusters.createLayer();
window.MapboxActivityClusters.update();
}
// ---------------------------------
// ACTIVITY MARKERS
// ---------------------------------
if (window.MapboxActivityMarkers) {
window.MapboxActivityMarkers.update(
state.activities,
);
}
}
// =================================
// STYLE LOAD
// =================================
mapboxMap.on(
"styledata",
() => {
if (!mapboxMap) {
return;
}
console.log(
"[MapboxMarkers] styledata",
);
initializeModules();
/*
* Non tentiamo di interrogare subito
* i layer appena creati.
*
* Aspettiamo che Mapbox abbia completato
* il rendering.
*/
mapboxMap.once(
"idle",
() => {
refreshMapboxMarkers(
"styledata → idle",
);
},
);
},
);
// =================================
// MOVE END
// =================================
mapboxMap.on(
"moveend",
() => {
console.log(
"[MapboxMarkers] moveend",
);
},
);
// =================================
// IDLE
// =================================
mapboxMap.on(
"idle",
() => {
if (!mapboxMap) {
return;
}
refreshMapboxMarkers(
"idle",
);
},
);
}
// ===================================
// REFRESH PHOTOS
// ===================================
function refreshPhotos() {
if (!mapboxMap) {
return;
}
// ---------------------------------
// Durante spiderfy non tocchiamo
// cluster e marker normali.
// ---------------------------------
if (
window.MapboxPhotoSpiderfy?.isOpen?.()
) {
return;
}
// =================================
// CLUSTER
// =================================
if (window.MapboxPhotoClusters) {
window.MapboxPhotoClusters.update();
}
// =================================
// MARKER
// =================================
if (window.MapboxPhotoMarkers) {
window.MapboxPhotoMarkers.update(
state.photos,
);
}
}
// ===================================
// REFRESH ACTIVITIES
// ===================================
function refreshActivities() {
if (!mapboxMap) {
return;
}
// =================================
// CLUSTER
// =================================
if (window.MapboxActivityClusters) {
window.MapboxActivityClusters.update();
}
// =================================
// MARKER
// =================================
if (window.MapboxActivityMarkers) {
window.MapboxActivityMarkers.update(
state.activities,
);
}
}
// ===================================
// REFRESH ROUTES
// ===================================
function refreshRoutes() {
/*
* Le routes vengono gestite
* direttamente da setRoutes().
*
* Non sono clusterizzate e non
* richiedono un modulo dedicato.
*/
}
// ===================================
// REFRESH COMPLETO
// ===================================
function refreshAll() {
if (!mapboxMap) {
return;
}
if (!mapboxMap.isStyleLoaded()) {
return;
}
initializeModules();
refreshPhotos();
refreshActivities();
refreshRoutes();
}
// ===================================
// PHOTOS
// ===================================
function setPhotos(features = []) {
state.photos.length = 0;
state.photos.push(...features);
console.log(
"[MapboxMarkers] photos:",
state.photos.length,
);
if (!mapboxMap) {
return;
}
if (!mapboxMap.isStyleLoaded()) {
return;
}
// =================================
// SOURCE
// =================================
if (window.PhotoSource) {
window.PhotoSource.update(
mapboxMap,
state.photos,
);
} else {
console.warn(
"[MapboxMarkers] PhotoSource non disponibile",
);
return;
}
// =================================
// CLUSTER LAYER
// =================================
/*
if (window.MapboxPhotoClusters) {
window.MapboxPhotoClusters.createLayer();
}
*/
/*
// =================================
// ATTESA IDLE
// =================================
mapboxMap.once(
"idle",
() => {
if (!mapboxMap) {
return;
}
console.log(
"[MapboxMarkers] setPhotos → idle → refreshPhotos",
);
refreshPhotos();
// Sicurezza: garantisce che il layer cluster
// esista e che venga interrogato dopo il rendering.
if (window.MapboxPhotoClusters) {
window.MapboxPhotoClusters.createLayer();
window.MapboxPhotoClusters.update();
}
},
);*/
}
// ===================================
// ACTIVITIES
// ===================================
function setActivities(features = []) {
state.activities.length = 0;
state.activities.push(...features);
console.log(
"[MapboxMarkers] activities:",
state.activities.length,
);
if (!mapboxMap) {
return;
}
if (!mapboxMap.isStyleLoaded()) {
return;
}
// =================================
// SOURCE
// =================================
if (window.ActivitySource) {
window.ActivitySource.update(
mapboxMap,
state.activities,
);
} else {
console.warn(
"[MapboxMarkers] ActivitySource non disponibile",
);
return;
}
// =================================
// CLUSTER LAYER
// =================================
if (window.MapboxActivityClusters) {
window.MapboxActivityClusters.createLayer();
}
// =================================
// ATTESA IDLE
// =================================
mapboxMap.once(
"idle",
() => {
if (!mapboxMap) {
return;
}
refreshActivities();
},
);
}
// ===================================
// ROUTES
// ===================================
function setRoutes(features = []) {
state.routes.length = 0;
state.routes.push(...features);
console.log(
"[MapboxMarkers] routes:",
state.routes.length,
);
if (!mapboxMap) {
return;
}
if (!mapboxMap.isStyleLoaded()) {
return;
}
const data = {
type: "FeatureCollection",
features: state.routes,
};
const source =
mapboxMap.getSource("routes");
// =================================
// SOURCE ESISTENTE
// =================================
if (source) {
source.setData(data);
} else {
// ===============================
// CREA SOURCE
// ===============================
mapboxMap.addSource("routes", {
type: "geojson",
data,
});
}
// =================================
// LAYER
// =================================
if (
!mapboxMap.getLayer(
"routes-line",
)
) {
mapboxMap.addLayer({
id: "routes-line",
type: "line",
source: "routes",
paint: {
"line-color": "#ff6b00",
"line-width": 4,
"line-opacity": 0.8,
},
});
}
}
// ===================================
// GET PHOTOS
// ===================================
function getPhotos() {
return state.photos;
}
// ===================================
// GET ACTIVITIES
// ===================================
function getActivities() {
return state.activities;
}
// ===================================
// GET ROUTES
// ===================================
function getRoutes() {
return state.routes;
}
// ===================================
// GET MAP
// ===================================
function getMap() {
return mapboxMap;
}
// ===================================
// DEBUG
// ===================================
function debug() {
console.log(
"[MapboxMarkers DEBUG]",
{
map: !!mapboxMap,
photos: state.photos.length,
activities:
state.activities.length,
routes:
state.routes.length,
photoSource:
!!mapboxMap?.getSource(
"photos",
),
photoClusters:
!!mapboxMap?.getLayer(
"photos-clusters",
),
photoMarkers:
window
.MapboxPhotoMarkers
?.size?.() ?? 0,
photoClusterMarkers:
window
.MapboxPhotoClusters
?.size?.() ?? 0,
spiderfy:
window
.MapboxPhotoSpiderfy
?.isOpen?.() ?? false,
spiderMarkers:
window
.MapboxPhotoSpiderfy
?.size?.() ?? 0,
activitySource:
!!mapboxMap?.getSource(
"activities",
),
activityClusters:
!!mapboxMap?.getLayer(
"activities-clusters",
),
activityMarkers:
window
.MapboxActivityMarkers
?.size?.() ?? 0,
activityClusterMarkers:
window
.MapboxActivityClusters
?.size?.() ?? 0,
routesSource:
!!mapboxMap?.getSource(
"routes",
),
routesLayer:
!!mapboxMap?.getLayer(
"routes-line",
),
},
);
}
// ===================================
// API PUBBLICA
// ===================================
window.debugMapboxMarkers = debug;
window.MapboxMarkers = {
setMap,
setPhotos,
setActivities,
setRoutes,
getPhotos,
getActivities,
getRoutes,
getMap,
refreshAll,
debug,
};
})();