8
This commit is contained in:
parent
9cfdef19df
commit
da0e3aa992
8 changed files with 245 additions and 1 deletions
|
|
@ -63,7 +63,13 @@
|
|||
</script>
|
||||
|
||||
<!-- 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>
|
||||
</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