8
This commit is contained in:
parent
9cfdef19df
commit
da0e3aa992
8 changed files with 245 additions and 1 deletions
|
|
@ -63,7 +63,13 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- App -->
|
<!-- App -->
|
||||||
<script src="app.js"></script>
|
<script src="js/config.js"></script>
|
||||||
|
<script src="js/data.js"></script>
|
||||||
|
<script src="js/gallery.js"></script>
|
||||||
|
<script src="js/modal.js"></script>
|
||||||
|
<script src="js/infoPanel.js"></script>
|
||||||
|
<script src="js/mapGlobal.js"></script>
|
||||||
|
<script src="js/main.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
12
js/config.js
Normal file
12
js/config.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// ===============================
|
||||||
|
// CONFIG & GLOBAL STATE
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
const API_URL = 'https://prova.patachina.it/photos';
|
||||||
|
|
||||||
|
let photosData = [];
|
||||||
|
let currentPhoto = null;
|
||||||
|
|
||||||
|
// Mappa globale
|
||||||
|
let globalMap = null;
|
||||||
|
let globalMarkers = null;
|
||||||
26
js/data.js
Normal file
26
js/data.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
// ===============================
|
||||||
|
// FETCH DELLE FOTO
|
||||||
|
// ===============================
|
||||||
|
async function loadPhotos() {
|
||||||
|
console.log("Inizio fetch:", API_URL);
|
||||||
|
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
res = await fetch(API_URL);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Errore fetch:", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = await res.text();
|
||||||
|
|
||||||
|
try {
|
||||||
|
photosData = JSON.parse(text);
|
||||||
|
console.log("JSON parse OK, numero foto:", photosData.length);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Errore nel parse JSON:", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderGallery(photosData);
|
||||||
|
}
|
||||||
40
js/gallery.js
Normal file
40
js/gallery.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
// ===============================
|
||||||
|
// RENDER GALLERIA
|
||||||
|
// ===============================
|
||||||
|
function renderGallery(photos) {
|
||||||
|
const gallery = document.getElementById('gallery');
|
||||||
|
gallery.innerHTML = '';
|
||||||
|
|
||||||
|
photos.forEach(photo => {
|
||||||
|
const thumbDiv = document.createElement('div');
|
||||||
|
thumbDiv.className = 'thumb';
|
||||||
|
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = `https://prova.patachina.it/${photo.thub1}`;
|
||||||
|
img.alt = photo.name || '';
|
||||||
|
img.loading = "lazy";
|
||||||
|
|
||||||
|
thumbDiv.appendChild(img);
|
||||||
|
|
||||||
|
if (photo.mime_type.startsWith("video/")) {
|
||||||
|
const play = document.createElement("div");
|
||||||
|
play.className = "play-icon";
|
||||||
|
play.textContent = "▶";
|
||||||
|
thumbDiv.appendChild(play);
|
||||||
|
}
|
||||||
|
|
||||||
|
const preview = photo.thub2
|
||||||
|
? `https://prova.patachina.it/${photo.thub2}`
|
||||||
|
: `https://prova.patachina.it/${photo.thub1}`;
|
||||||
|
|
||||||
|
thumbDiv.addEventListener('click', () => {
|
||||||
|
openModal(
|
||||||
|
`https://prova.patachina.it/${photo.path}`,
|
||||||
|
preview,
|
||||||
|
photo
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
gallery.appendChild(thumbDiv);
|
||||||
|
});
|
||||||
|
}
|
||||||
57
js/infoPanel.js
Normal file
57
js/infoPanel.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// ===============================
|
||||||
|
// PANNELLO INFO + MAPPA
|
||||||
|
// ===============================
|
||||||
|
const infoPanel = document.getElementById('infoPanel');
|
||||||
|
const infoBtn = document.getElementById('modalInfoBtn');
|
||||||
|
|
||||||
|
infoBtn.addEventListener('click', () => {
|
||||||
|
if (!currentPhoto) return;
|
||||||
|
|
||||||
|
const gps = currentPhoto.gps || { lat: '-', lng: '-', alt: '-' };
|
||||||
|
const folder = currentPhoto.path.split('/').slice(2, -1).join('/');
|
||||||
|
|
||||||
|
infoPanel.innerHTML = `
|
||||||
|
<h3>Informazioni</h3>
|
||||||
|
|
||||||
|
<div class="info-row"><b>Nome:</b> ${currentPhoto.name}</div>
|
||||||
|
<div class="info-row"><b>Data:</b> ${currentPhoto.taken_at}</div>
|
||||||
|
|
||||||
|
<div class="info-row"><b>Latitudine:</b> ${gps.lat}</div>
|
||||||
|
<div class="info-row"><b>Longitudine:</b> ${gps.lng}</div>
|
||||||
|
<div class="info-row"><b>Altitudine:</b> ${gps.alt} m</div>
|
||||||
|
|
||||||
|
<div class="info-row"><b>Dimensioni:</b> ${currentPhoto.width} × ${currentPhoto.height}</div>
|
||||||
|
<div class="info-row"><b>Peso:</b> ${(currentPhoto.size_bytes / 1024 / 1024).toFixed(2)} MB</div>
|
||||||
|
<div class="info-row"><b>Tipo:</b> ${currentPhoto.mime_type}</div>
|
||||||
|
|
||||||
|
<div class="info-row"><b>Cartella:</b> ${folder}</div>
|
||||||
|
|
||||||
|
${gps.lat !== '-' ? '<div id="infoMap" class="info-map"></div>' : ''}
|
||||||
|
`;
|
||||||
|
|
||||||
|
infoPanel.classList.add('open');
|
||||||
|
|
||||||
|
if (gps.lat !== '-' && gps.lng !== '-') {
|
||||||
|
setTimeout(() => {
|
||||||
|
const map = L.map('infoMap', {
|
||||||
|
zoomControl: false,
|
||||||
|
attributionControl: false
|
||||||
|
}).setView([gps.lat, gps.lng], 13);
|
||||||
|
|
||||||
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
maxZoom: 19
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
L.marker([gps.lat, gps.lng]).addTo(map);
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!infoPanel.classList.contains('open')) return;
|
||||||
|
|
||||||
|
const inside = infoPanel.contains(e.target);
|
||||||
|
const btn = infoBtn.contains(e.target);
|
||||||
|
|
||||||
|
if (!inside && !btn) infoPanel.classList.remove('open');
|
||||||
|
});
|
||||||
5
js/main.js
Normal file
5
js/main.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// ===============================
|
||||||
|
// AVVIO
|
||||||
|
// ===============================
|
||||||
|
console.log("main.js avviato");
|
||||||
|
loadPhotos();
|
||||||
51
js/mapGlobal.js
Normal file
51
js/mapGlobal.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
// ===============================
|
||||||
|
// MAPPA GLOBALE
|
||||||
|
// ===============================
|
||||||
|
document.getElementById("openMapBtn").addEventListener("click", openGlobalMap);
|
||||||
|
|
||||||
|
function openGlobalMap() {
|
||||||
|
const mapDiv = document.getElementById("globalMap");
|
||||||
|
const gallery = document.getElementById("gallery");
|
||||||
|
|
||||||
|
const isOpen = mapDiv.classList.contains("open");
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
mapDiv.classList.remove("open");
|
||||||
|
gallery.classList.remove("hidden");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapDiv.classList.add("open");
|
||||||
|
gallery.classList.add("hidden");
|
||||||
|
|
||||||
|
if (!globalMap) {
|
||||||
|
globalMap = L.map("globalMap").setView([42.5, 12.5], 6);
|
||||||
|
|
||||||
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
maxZoom: 19
|
||||||
|
}).addTo(globalMap);
|
||||||
|
|
||||||
|
globalMarkers = L.markerClusterGroup();
|
||||||
|
globalMap.addLayer(globalMarkers);
|
||||||
|
|
||||||
|
photosData.forEach(photo => {
|
||||||
|
if (!photo.gps || !photo.gps.lat || !photo.gps.lng) return;
|
||||||
|
|
||||||
|
const marker = L.marker([photo.gps.lat, photo.gps.lng]);
|
||||||
|
|
||||||
|
marker.on("click", () => {
|
||||||
|
openModal(
|
||||||
|
`https://prova.patachina.it/${photo.path}`,
|
||||||
|
photo.thub2
|
||||||
|
? `https://prova.patachina.it/${photo.thub2}`
|
||||||
|
: `https://prova.patachina.it/${photo.thub1}`,
|
||||||
|
photo
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
globalMarkers.addLayer(marker);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => globalMap.invalidateSize(), 200);
|
||||||
|
}
|
||||||
47
js/modal.js
Normal file
47
js/modal.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// ===============================
|
||||||
|
// MODALE (FOTO + VIDEO)
|
||||||
|
// ===============================
|
||||||
|
const modal = document.getElementById('modal');
|
||||||
|
const modalClose = document.getElementById('modalClose');
|
||||||
|
|
||||||
|
function openModal(srcOriginal, srcPreview, photo) {
|
||||||
|
currentPhoto = photo;
|
||||||
|
|
||||||
|
const container = document.getElementById("modalMediaContainer");
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
if (photo.mime_type.startsWith("video/")) {
|
||||||
|
const video = document.createElement("video");
|
||||||
|
video.src = srcOriginal;
|
||||||
|
video.controls = true;
|
||||||
|
video.autoplay = true;
|
||||||
|
video.style.maxWidth = "100%";
|
||||||
|
video.style.maxHeight = "100%";
|
||||||
|
container.appendChild(video);
|
||||||
|
} else {
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = srcPreview;
|
||||||
|
img.style.maxWidth = "100%";
|
||||||
|
img.style.maxHeight = "100%";
|
||||||
|
img.style.objectFit = "contain";
|
||||||
|
container.appendChild(img);
|
||||||
|
|
||||||
|
const full = new Image();
|
||||||
|
full.src = srcOriginal;
|
||||||
|
full.onload = () => {
|
||||||
|
img.src = srcOriginal;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
modal.classList.add('open');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
modal.classList.remove('open');
|
||||||
|
document.getElementById("modalMediaContainer").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
modalClose.addEventListener('click', closeModal);
|
||||||
|
modal.addEventListener('click', (e) => {
|
||||||
|
if (e.target === modal) closeModal();
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue