960 lines
18 KiB
JavaScript
960 lines
18 KiB
JavaScript
// public/js/map/terrain3d.js
|
|
// Switch Leaflet <-> Mapbox GL Terrain 3D
|
|
|
|
(() => {
|
|
"use strict";
|
|
|
|
let mapboxMap = null;
|
|
let enabled = false;
|
|
let savedLeafletView = null;
|
|
let savedLeafletMap = null;
|
|
let terrainMarkerRefreshTimer = null;
|
|
let terrainMarkerRefreshToken = 0;
|
|
let terrainEventsMap = null;
|
|
let destroying = false;
|
|
|
|
function getToken() {
|
|
return window.AppConfig?.mapboxToken || "";
|
|
}
|
|
|
|
function getContainer() {
|
|
return document.getElementById("terrainMap");
|
|
}
|
|
|
|
function getLeafletMap() {
|
|
if (window.MapEngine?.type === "mapbox") {
|
|
return savedLeafletMap;
|
|
}
|
|
|
|
return (
|
|
window.GlobalMap?.getMap?.() ||
|
|
window.MapEngine?.map ||
|
|
window.leafletMap ||
|
|
null
|
|
);
|
|
}
|
|
|
|
function createMapbox3D() {
|
|
const container = getContainer();
|
|
|
|
if (!container) {
|
|
console.error("[Terrain3D] #terrainMap non trovato");
|
|
|
|
return;
|
|
}
|
|
|
|
const token = getToken();
|
|
|
|
if (!token) {
|
|
console.error("[Terrain3D] Token Mapbox mancante");
|
|
|
|
return;
|
|
}
|
|
|
|
if (!window.mapboxgl) {
|
|
console.error("[Terrain3D] Mapbox GL JS non caricato");
|
|
|
|
return;
|
|
}
|
|
|
|
// Impedisce la creazione
|
|
// di una seconda istanza.
|
|
if (mapboxMap) {
|
|
console.warn("[Terrain3D] Mapbox già inizializzato");
|
|
|
|
return;
|
|
}
|
|
|
|
// =================================
|
|
// MOSTRA IL CONTENITORE MAPBOX
|
|
// =================================
|
|
|
|
container.classList.add("open");
|
|
|
|
container.style.display = "block";
|
|
|
|
container.style.visibility = "visible";
|
|
|
|
container.style.pointerEvents = "auto";
|
|
|
|
// =================================
|
|
// RECUPERA LA MAPPA LEAFLET
|
|
// =================================
|
|
|
|
if (!savedLeafletMap) {
|
|
savedLeafletMap = getLeafletMap();
|
|
}
|
|
|
|
const leafletMap = savedLeafletMap;
|
|
|
|
console.log("[Terrain3D] Leaflet trovato:", leafletMap);
|
|
|
|
// =================================
|
|
// VISTA INIZIALE
|
|
// =================================
|
|
|
|
let center = [12.4964, 41.9028];
|
|
|
|
let zoom = 6;
|
|
|
|
if (leafletMap) {
|
|
const leafletCenter = leafletMap.getCenter();
|
|
|
|
center = [leafletCenter.lng, leafletCenter.lat];
|
|
|
|
zoom = leafletMap.getZoom();
|
|
|
|
savedLeafletView = {
|
|
lat: leafletCenter.lat,
|
|
|
|
lng: leafletCenter.lng,
|
|
|
|
zoom: leafletMap.getZoom(),
|
|
};
|
|
|
|
console.log("[Terrain3D] Vista Leaflet salvata", savedLeafletView);
|
|
}
|
|
|
|
// =================================
|
|
// NASCONDE LEAFLET
|
|
// =================================
|
|
|
|
if (leafletMap) {
|
|
const leafletMapContainer = leafletMap.getContainer();
|
|
|
|
leafletMapContainer.style.visibility = "hidden";
|
|
|
|
leafletMapContainer.style.pointerEvents = "none";
|
|
|
|
console.log("[Terrain3D] Leaflet nascosto");
|
|
}
|
|
|
|
// =================================
|
|
// CREA MAPBOX
|
|
// =================================
|
|
|
|
mapboxgl.accessToken = token;
|
|
|
|
mapboxMap = new mapboxgl.Map({
|
|
container,
|
|
|
|
style: "mapbox://styles/mapbox/outdoors-v12",
|
|
|
|
center,
|
|
zoom,
|
|
|
|
pitch: 60,
|
|
bearing: -20,
|
|
|
|
antialias: true,
|
|
});
|
|
|
|
// =================================
|
|
// CARICAMENTO MAPBOX
|
|
// =================================
|
|
|
|
mapboxMap.on("load", () => {
|
|
if (!mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
// -------------------------------
|
|
// SOURCE DEL TERRENO
|
|
// -------------------------------
|
|
|
|
if (!mapboxMap.getSource("mapbox-dem")) {
|
|
mapboxMap.addSource("mapbox-dem", {
|
|
type: "raster-dem",
|
|
|
|
url: "mapbox://mapbox.mapbox-terrain-dem-v1",
|
|
|
|
tileSize: 512,
|
|
maxzoom: 14,
|
|
});
|
|
}
|
|
|
|
// -------------------------------
|
|
// TERRENO 3D
|
|
// -------------------------------
|
|
|
|
mapboxMap.setTerrain({
|
|
source: "mapbox-dem",
|
|
|
|
exaggeration: 1.5,
|
|
});
|
|
|
|
// -------------------------------
|
|
// CONTROLLI MAPBOX
|
|
// -------------------------------
|
|
|
|
mapboxMap.addControl(
|
|
new mapboxgl.NavigationControl(),
|
|
|
|
"top-right",
|
|
);
|
|
|
|
// -------------------------------
|
|
// COLLEGA MAPENGINE
|
|
// -------------------------------
|
|
|
|
if (window.MapEngine) {
|
|
window.MapEngine.setMapbox(mapboxMap);
|
|
}
|
|
|
|
// -------------------------------
|
|
// COLLEGA MARKER CONTROLLER
|
|
// -------------------------------
|
|
|
|
window.MapboxMarkers?.setMap?.(mapboxMap);
|
|
|
|
window.MapBaseLayers?.mountTerrainStyleControl?.(container);
|
|
|
|
// -------------------------------
|
|
// ATTIVA MAPBOX 3D
|
|
// -------------------------------
|
|
|
|
/*
|
|
* enabled deve diventare true prima
|
|
* di registrare e utilizzare il refresh.
|
|
*/
|
|
|
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const activitiesMode =
|
|
window.state?.mode ===
|
|
"activities";
|
|
|
|
if (activitiesMode) {
|
|
window.showActivityRoutesToggle?.();
|
|
} else {
|
|
window.hideActivityRoutesToggle?.(
|
|
true,
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------
|
|
// COLLEGA MOVEEND
|
|
// -------------------------------
|
|
|
|
/*
|
|
* Registra il listener nominato
|
|
* handleTerrainMoveEnd.
|
|
*
|
|
* Non devono esserci altri listener
|
|
* anonimi moveend in questa funzione.
|
|
*/
|
|
setupTerrainMapEvents();
|
|
|
|
// -------------------------------
|
|
// PRIMO REFRESH
|
|
// -------------------------------
|
|
|
|
/*
|
|
* Aspetta il completamento del primo
|
|
* rendering prima di caricare marker,
|
|
* cluster e route.
|
|
*/
|
|
mapboxMap.once("idle", () => {
|
|
scheduleTerrainMarkerRefresh("initial-idle");
|
|
});
|
|
|
|
console.log("[Terrain3D] Mapbox 3D attivo");
|
|
|
|
// -------------------------------
|
|
// AGGIORNA LE DIMENSIONI
|
|
// -------------------------------
|
|
|
|
requestAnimationFrame(() => {
|
|
mapboxMap?.resize?.();
|
|
});
|
|
});
|
|
|
|
// =================================
|
|
// ERRORI MAPBOX
|
|
// =================================
|
|
|
|
mapboxMap.on("error", (event) => {
|
|
console.error("[Terrain3D] errore Mapbox", event?.error || event);
|
|
});
|
|
}
|
|
|
|
|
|
function destroyMapbox3D() {
|
|
if (!mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
destroying = true;
|
|
console.log("[Terrain3D] Chiusura MapboxGL");
|
|
|
|
const mapboxCenter = mapboxMap.getCenter?.();
|
|
|
|
const mapboxZoom = mapboxMap.getZoom?.();
|
|
|
|
if (
|
|
mapboxCenter &&
|
|
Number.isFinite(Number(mapboxCenter.lat)) &&
|
|
Number.isFinite(Number(mapboxCenter.lng)) &&
|
|
Number.isFinite(Number(mapboxZoom))
|
|
) {
|
|
savedLeafletView = {
|
|
lat: Number(mapboxCenter.lat),
|
|
|
|
lng: Number(mapboxCenter.lng),
|
|
|
|
zoom: Number(mapboxZoom),
|
|
};
|
|
}
|
|
|
|
removeTerrainMapEvents();
|
|
|
|
/*
|
|
* Pulisce marker e cluster mentre
|
|
* la vecchia mappa è ancora valida.
|
|
*/
|
|
window.MapboxMarkers?.clearMarkers?.();
|
|
|
|
window.MapBaseLayers?.removeTerrainStyleControl?.();
|
|
|
|
/*
|
|
* Soltanto dopo la pulizia viene
|
|
* distrutta l'istanza Mapbox.
|
|
*/
|
|
mapboxMap.remove();
|
|
mapboxMap = null;
|
|
enabled = false;
|
|
destroying = false;
|
|
|
|
const terrainContainer = document.getElementById("terrainMap");
|
|
|
|
if (terrainContainer) {
|
|
terrainContainer.classList.remove("open");
|
|
|
|
terrainContainer.style.display = "none";
|
|
}
|
|
|
|
const globalMapContainer = document.getElementById("globalMap");
|
|
|
|
if (globalMapContainer) {
|
|
globalMapContainer.style.visibility = "visible";
|
|
|
|
globalMapContainer.classList.add("open");
|
|
}
|
|
|
|
const leafletMap = savedLeafletMap;
|
|
|
|
if (leafletMap) {
|
|
const leafletMapContainer = leafletMap.getContainer();
|
|
|
|
leafletMapContainer.style.display = "block";
|
|
|
|
leafletMapContainer.style.visibility = "visible";
|
|
|
|
leafletMapContainer.style.pointerEvents = "auto";
|
|
|
|
leafletMap.invalidateSize();
|
|
|
|
if (savedLeafletView) {
|
|
leafletMap.setView(
|
|
[savedLeafletView.lat, savedLeafletView.lng],
|
|
savedLeafletView.zoom,
|
|
);
|
|
}
|
|
|
|
console.log("[Terrain3D] Leaflet ripristinato");
|
|
}
|
|
|
|
if (
|
|
savedLeafletMap &&
|
|
window.MapEngine
|
|
) {
|
|
window.MapEngine.type =
|
|
"leaflet";
|
|
|
|
window.MapEngine.map =
|
|
savedLeafletMap;
|
|
|
|
window.MapEngine.markerLayer =
|
|
window.globalMarkers;
|
|
}
|
|
|
|
requestAnimationFrame(
|
|
async () => {
|
|
if (!savedLeafletMap) {
|
|
return;
|
|
}
|
|
|
|
savedLeafletMap.invalidateSize?.();
|
|
|
|
if (
|
|
window.globalMarkers &&
|
|
!savedLeafletMap.hasLayer(
|
|
window.globalMarkers,
|
|
)
|
|
) {
|
|
savedLeafletMap.addLayer(
|
|
window.globalMarkers,
|
|
);
|
|
}
|
|
|
|
window.globalMarkers
|
|
?.clearLayers?.();
|
|
|
|
if (
|
|
window.state?.mode ===
|
|
"activities"
|
|
) {
|
|
await window
|
|
.renderActivityMapLayer?.();
|
|
} else {
|
|
await window
|
|
.renderPhotoMapLayer?.();
|
|
}
|
|
|
|
savedLeafletMap.invalidateSize?.();
|
|
|
|
console.log(
|
|
"[Terrain3D] Leaflet ridisegnato",
|
|
{
|
|
mode:
|
|
window.state?.mode,
|
|
|
|
markerLayers:
|
|
window.globalMarkers
|
|
?.getLayers?.()
|
|
?.length ?? null,
|
|
|
|
clusterOnMap:
|
|
!!(
|
|
window.globalMarkers &&
|
|
savedLeafletMap.hasLayer(
|
|
window.globalMarkers,
|
|
)
|
|
),
|
|
},
|
|
);
|
|
},
|
|
);
|
|
|
|
console.log(
|
|
"[Terrain3D] ritorno Leaflet",
|
|
);
|
|
}
|
|
|
|
function waitForMapboxReady(timeoutMs = 2500) {
|
|
return new Promise((resolve) => {
|
|
if (!mapboxMap) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
if (mapboxMap.isStyleLoaded?.() && !mapboxMap.isMoving?.()) {
|
|
resolve(true);
|
|
return;
|
|
}
|
|
|
|
let completed = false;
|
|
|
|
const finish = () => {
|
|
if (completed) {
|
|
return;
|
|
}
|
|
|
|
completed = true;
|
|
|
|
clearTimeout(timeout);
|
|
|
|
mapboxMap?.off?.("idle", handleReady);
|
|
|
|
resolve(!!mapboxMap && !!mapboxMap.isStyleLoaded?.());
|
|
};
|
|
|
|
const handleReady = () => {
|
|
if (!mapboxMap) {
|
|
finish();
|
|
return;
|
|
}
|
|
|
|
if (mapboxMap.isStyleLoaded?.() && !mapboxMap.isMoving?.()) {
|
|
finish();
|
|
}
|
|
};
|
|
|
|
const timeout = setTimeout(finish, timeoutMs);
|
|
|
|
mapboxMap.on("idle", handleReady);
|
|
});
|
|
}
|
|
|
|
function scheduleTerrainMarkerRefresh(reason = "moveend") {
|
|
if (!mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
|
|
if (destroying) {
|
|
return;
|
|
}
|
|
|
|
if (terrainMarkerRefreshTimer) {
|
|
clearTimeout(terrainMarkerRefreshTimer);
|
|
}
|
|
|
|
const token = ++terrainMarkerRefreshToken;
|
|
|
|
terrainMarkerRefreshTimer = setTimeout(async () => {
|
|
terrainMarkerRefreshTimer = null;
|
|
|
|
if (!mapboxMap || !enabled) {
|
|
return;
|
|
}
|
|
|
|
if (token !== terrainMarkerRefreshToken) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Dopo moveend Mapbox può ancora
|
|
* avere isStyleLoaded() false.
|
|
* Aspettiamo il successivo idle.
|
|
*/
|
|
const ready = await waitForMapboxReady();
|
|
|
|
if (!ready || !mapboxMap || !enabled) {
|
|
console.warn("[Terrain3D] refresh annullato, Mapbox non pronto", {
|
|
reason,
|
|
token,
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
if (token !== terrainMarkerRefreshToken) {
|
|
return;
|
|
}
|
|
|
|
if (typeof window.refreshTerrainMarkers !== "function") {
|
|
return;
|
|
}
|
|
|
|
console.log("[Terrain3D] aggiorno marker", {
|
|
reason,
|
|
token,
|
|
|
|
styleLoaded: mapboxMap.isStyleLoaded?.(),
|
|
|
|
moving: mapboxMap.isMoving?.(),
|
|
|
|
zoom: mapboxMap.getZoom?.(),
|
|
|
|
bounds: mapboxMap.getBounds?.()?.toArray?.(),
|
|
});
|
|
|
|
await window.refreshTerrainMarkers();
|
|
}, 180);
|
|
}
|
|
|
|
function handleTerrainMoveEnd() {
|
|
scheduleTerrainMarkerRefresh("moveend");
|
|
}
|
|
|
|
function setupTerrainMapEvents() {
|
|
if (!mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
if (terrainEventsMap === mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
removeTerrainMapEvents();
|
|
|
|
terrainEventsMap = mapboxMap;
|
|
|
|
terrainEventsMap.on("moveend", handleTerrainMoveEnd);
|
|
|
|
console.log("[Terrain3D] listener moveend collegato");
|
|
}
|
|
|
|
function removeTerrainMapEvents() {
|
|
if (terrainMarkerRefreshTimer) {
|
|
clearTimeout(terrainMarkerRefreshTimer);
|
|
|
|
terrainMarkerRefreshTimer = null;
|
|
}
|
|
|
|
terrainMarkerRefreshToken++;
|
|
|
|
if (!terrainEventsMap) {
|
|
return;
|
|
}
|
|
|
|
terrainEventsMap.off("moveend", handleTerrainMoveEnd);
|
|
|
|
terrainEventsMap = null;
|
|
|
|
console.log("[Terrain3D] listener moveend rimosso");
|
|
}
|
|
|
|
async function enable() {
|
|
// Mapbox è già attivo.
|
|
if (enabled && mapboxMap) {
|
|
mapboxMap.resize?.();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Rimuove un'istanza rimasta
|
|
// parzialmente inizializzata.
|
|
if (mapboxMap && !enabled) {
|
|
console.warn("[Terrain3D] rimuovo istanza Mapbox incompleta");
|
|
|
|
try {
|
|
removeTerrainMapEvents();
|
|
|
|
window.MapBaseLayers?.removeTerrainStyleControl?.();
|
|
|
|
window.MapboxMarkers?.clearMarkers?.();
|
|
|
|
mapboxMap.remove();
|
|
} catch (error) {
|
|
console.warn("[Terrain3D] errore pulizia istanza incompleta", error);
|
|
}
|
|
|
|
mapboxMap = null;
|
|
}
|
|
|
|
// Avvia una nuova istanza Mapbox.
|
|
createMapbox3D();
|
|
|
|
const success = await new Promise((resolve) => {
|
|
let completed = false;
|
|
let check = null;
|
|
let timeout = null;
|
|
|
|
const finish = (result) => {
|
|
if (completed) {
|
|
return;
|
|
}
|
|
|
|
completed = true;
|
|
|
|
if (check !== null) {
|
|
clearInterval(check);
|
|
|
|
check = null;
|
|
}
|
|
|
|
if (timeout !== null) {
|
|
clearTimeout(timeout);
|
|
|
|
timeout = null;
|
|
}
|
|
|
|
resolve(result);
|
|
};
|
|
|
|
check = setInterval(() => {
|
|
if (!mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
|
|
if (!mapboxMap.isStyleLoaded?.()) {
|
|
return;
|
|
}
|
|
|
|
mapboxMap.resize?.();
|
|
|
|
finish(true);
|
|
}, 50);
|
|
|
|
timeout = setTimeout(() => {
|
|
finish(false);
|
|
}, 10000);
|
|
});
|
|
|
|
window.updateTerrainButton?.(enabled);
|
|
|
|
if (!success) {
|
|
console.warn("[Terrain3D] attivazione non completata entro 10 secondi");
|
|
|
|
// Pulisce l'istanza che non ha
|
|
// completato correttamente il load.
|
|
if (mapboxMap) {
|
|
try {
|
|
removeTerrainMapEvents();
|
|
|
|
window.MapBaseLayers?.removeTerrainStyleControl?.();
|
|
|
|
window.MapboxMarkers?.clearMarkers?.();
|
|
|
|
mapboxMap.remove();
|
|
} catch (error) {
|
|
console.warn("[Terrain3D] errore pulizia dopo timeout", error);
|
|
}
|
|
}
|
|
|
|
mapboxMap = null;
|
|
enabled = false;
|
|
|
|
window.updateTerrainButton?.(false);
|
|
|
|
return false;
|
|
}
|
|
|
|
console.log("[Terrain3D] attivazione completata");
|
|
|
|
return true;
|
|
}
|
|
|
|
function disable() {
|
|
if (!mapboxMap) {
|
|
enabled = false;
|
|
|
|
window.updateTerrainButton?.(false);
|
|
|
|
return;
|
|
}
|
|
|
|
destroyMapbox3D();
|
|
|
|
enabled = false;
|
|
|
|
window.updateTerrainButton?.(false);
|
|
}
|
|
|
|
async function toggle() {
|
|
if (enabled) {
|
|
disable();
|
|
} else {
|
|
await enable();
|
|
}
|
|
}
|
|
|
|
function isEnabled() {
|
|
return enabled;
|
|
}
|
|
|
|
function isActivityItem(item) {
|
|
if (!item) {
|
|
return false;
|
|
}
|
|
|
|
const format = String(
|
|
item.format ||
|
|
item.file_extension ||
|
|
item.mime_type ||
|
|
item.file_name ||
|
|
item.name ||
|
|
"",
|
|
).toLowerCase();
|
|
|
|
return (
|
|
format.includes("fit") ||
|
|
format.includes("gpx") ||
|
|
format.includes("tcx") ||
|
|
item.distance_meters != null ||
|
|
item.duration_millis != null ||
|
|
item.track_preview != null
|
|
);
|
|
}
|
|
|
|
window.refreshTerrainMarkers = async function () {
|
|
if (!mapboxMap) {
|
|
return;
|
|
}
|
|
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
|
|
if (destroying) {
|
|
return;
|
|
}
|
|
|
|
const items =
|
|
typeof window.getLocalItems === "function" ? window.getLocalItems() : [];
|
|
|
|
const isActivitiesMode =
|
|
window.state?.mode ===
|
|
"activities";
|
|
|
|
let photos = [];
|
|
let activities = [];
|
|
let routes = [];
|
|
|
|
if (isActivitiesMode) {
|
|
window.showActivityRoutesToggle?.();
|
|
|
|
if (
|
|
window.MapboxPhotoSpiderfy
|
|
?.isOpen?.()
|
|
) {
|
|
window.MapboxPhotoSpiderfy
|
|
?.clear?.();
|
|
}
|
|
|
|
window.MapboxPhotoMarkers
|
|
?.clear?.();
|
|
|
|
window.MapboxPhotoClusters
|
|
?.clear?.();
|
|
|
|
window.MapboxMarkers
|
|
?.setPhotos?.([]);
|
|
|
|
activities =
|
|
typeof window
|
|
.getActivityMapGeoJSON ===
|
|
"function"
|
|
? window
|
|
.getActivityMapGeoJSON()
|
|
: [];
|
|
|
|
routes =
|
|
typeof window
|
|
.getActivityRoutesGeoJSON ===
|
|
"function"
|
|
? window
|
|
.getActivityRoutesGeoJSON()
|
|
: [];
|
|
|
|
if (
|
|
activities.length === 0 &&
|
|
typeof window
|
|
.renderActivityMapLayer ===
|
|
"function"
|
|
) {
|
|
console.log(
|
|
"[Terrain3D] caricamento iniziale attività",
|
|
{
|
|
localItems:
|
|
items.length,
|
|
},
|
|
);
|
|
|
|
await window
|
|
.renderActivityMapLayer();
|
|
|
|
activities =
|
|
typeof window
|
|
.getActivityMapGeoJSON ===
|
|
"function"
|
|
? window
|
|
.getActivityMapGeoJSON()
|
|
: [];
|
|
|
|
routes =
|
|
typeof window
|
|
.getActivityRoutesGeoJSON ===
|
|
"function"
|
|
? window
|
|
.getActivityRoutesGeoJSON()
|
|
: [];
|
|
}
|
|
|
|
window.MapboxMarkers
|
|
?.setActivities?.(
|
|
activities,
|
|
);
|
|
|
|
const showRoutes =
|
|
window
|
|
.areActivityRoutesVisible?.() ??
|
|
false;
|
|
|
|
window.MapboxMarkers
|
|
?.setRoutes?.(
|
|
showRoutes
|
|
? routes
|
|
: [],
|
|
);
|
|
} else {
|
|
window.hideActivityRoutesToggle?.(
|
|
true,
|
|
);
|
|
|
|
if (
|
|
window.MapboxActivitySpiderfy
|
|
?.isOpen?.()
|
|
) {
|
|
window.MapboxActivitySpiderfy
|
|
?.clear?.();
|
|
}
|
|
|
|
window.MapboxActivityMarkers
|
|
?.clear?.();
|
|
|
|
window.MapboxActivityClusters
|
|
?.clear?.();
|
|
|
|
window.MapboxMarkers
|
|
?.setActivities?.([]);
|
|
|
|
window.MapboxMarkers
|
|
?.setRoutes?.([]);
|
|
|
|
photos =
|
|
typeof window
|
|
.getPhotoMapGeoJSON ===
|
|
"function"
|
|
? window
|
|
.getPhotoMapGeoJSON()
|
|
: [];
|
|
|
|
window.MapboxMarkers
|
|
?.setPhotos?.(
|
|
photos,
|
|
);
|
|
}
|
|
|
|
console.log("[Terrain3D] marker aggiornati", {
|
|
mode: isActivitiesMode ? "activities" : "photos",
|
|
|
|
localItems: items.length,
|
|
|
|
photos: photos.length,
|
|
|
|
activities: activities.length,
|
|
|
|
routesAvailable: routes.length,
|
|
|
|
routesVisible: isActivitiesMode
|
|
? (window.areActivityRoutesVisible?.() ?? false)
|
|
: false,
|
|
|
|
styleLoaded: !!mapboxMap?.isStyleLoaded?.(),
|
|
|
|
moving: !!mapboxMap?.isMoving?.(),
|
|
});
|
|
};
|
|
|
|
window.MapTerrain3D = Object.freeze({
|
|
enable,
|
|
disable,
|
|
toggle,
|
|
enabled: isEnabled,
|
|
});
|
|
})();
|