430 lines
7.5 KiB
Text
430 lines
7.5 KiB
Text
// 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,
|
|
};
|
|
})();
|