mem / index.html
vishnumeher's picture
Add 2 files
32e8426 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Memories Gallery</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.gallery-container {
position: relative;
overflow: hidden;
height: 80vh;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 16px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
}
.gallery-track {
display: flex;
transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1);
height: 100%;
}
.memory-slide {
min-width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: relative;
padding: 20px;
box-sizing: border-box;
}
.memory-image {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 12px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease;
}
.memory-image:hover {
transform: scale(1.02);
}
.memory-info {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: rgba(255, 255, 255, 0.9);
color: #333;
padding: 12px 24px;
border-radius: 30px;
font-size: 1rem;
font-weight: 600;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.gallery-nav {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 12px;
z-index: 10;
}
.nav-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
border: 2px solid rgba(255, 255, 255, 0.8);
cursor: pointer;
transition: all 0.3s ease;
}
.nav-dot.active {
background: white;
transform: scale(1.3);
border-color: white;
}
.loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(0, 0, 0, 0.1);
border-radius: 50%;
border-top-color: #4f46e5;
animation: spin 1s ease-in-out infinite;
margin-bottom: 20px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@media (max-width: 768px) {
.gallery-container {
height: 60vh;
}
.memory-info {
font-size: 0.9rem;
padding: 8px 16px;
bottom: 20px;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen flex flex-col items-center justify-center p-4">
<div class="w-full max-w-6xl mx-auto">
<h1 class="text-4xl md:text-5xl font-bold text-center mb-8 text-gray-800">
<span class="text-indigo-600">Memories</span> Gallery
</h1>
<div class="gallery-container">
<div class="loading-overlay">
<div class="spinner"></div>
<p class="text-gray-700 font-medium">Loading your memories...</p>
</div>
<div class="gallery-track"></div>
<div class="gallery-nav"></div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const galleryTrack = document.querySelector('.gallery-track');
const galleryNav = document.querySelector('.gallery-nav');
const loadingOverlay = document.querySelector('.loading-overlay');
let currentSlide = 0;
let slideInterval;
const slideDuration = 4000; // 4 seconds per slide
let imageFiles = [];
// Function to get all image files from the same directory
async function loadImagesFromDirectory() {
try {
// This will only work if the HTML file is served from a web server
const response = await fetch(window.location.href);
const html = await response.text();
// Parse HTML to find image files (simplified approach)
// Note: This is a basic implementation and may not catch all images
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const images = doc.querySelectorAll('img');
// Get all image files in the same directory
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
const directoryPath = window.location.href.substring(0, window.location.href.lastIndexOf('/') + 1);
// In a real scenario, you would need server-side code to list files
// For this demo, we'll use a placeholder approach
console.log("Note: In a real implementation, you would need server-side code to list all image files in the directory.");
// For demo purposes, we'll create some placeholder images
// Replace this with actual image loading logic for your implementation
const placeholderImages = [
{ name: 'memory1.jpg', caption: 'Beautiful Day' },
{ name: 'memory2.jpg', caption: 'Family Gathering' },
{ name: 'memory3.jpg', caption: 'Vacation Time' },
{ name: 'memory4.jpg', caption: 'Special Moment' },
{ name: 'memory5.jpg', caption: 'Celebration' }
];
return placeholderImages.map(img => {
return {
url: img.name,
caption: img.caption
};
});
} catch (error) {
console.error("Error loading images:", error);
return [];
}
}
// Initialize gallery
async function initGallery() {
// Load images from the same directory
imageFiles = await loadImagesFromDirectory();
if (imageFiles.length === 0) {
loadingOverlay.innerHTML = `
<div class="text-center p-6">
<i class="fas fa-image text-4xl text-gray-400 mb-4"></i>
<h3 class="text-xl font-medium text-gray-700">No images found</h3>
<p class="text-gray-600 mt-2">Place your image files in the same folder as this HTML file</p>
</div>
`;
return;
}
// Create slides
imageFiles.forEach((image, index) => {
// Create slide element
const slide = document.createElement('div');
slide.className = 'memory-slide';
// Create image element
const img = document.createElement('img');
img.src = image.url;
img.alt = image.caption || `Memory ${index + 1}`;
img.className = 'memory-image';
img.loading = 'lazy';
// Create caption element
const caption = document.createElement('div');
caption.className = 'memory-info';
caption.textContent = image.caption || `Memory ${index + 1}`;
// Append elements
slide.appendChild(img);
slide.appendChild(caption);
galleryTrack.appendChild(slide);
// Create navigation dot
const navDot = document.createElement('div');
navDot.className = 'nav-dot';
navDot.dataset.index = index;
navDot.addEventListener('click', () => goToSlide(index));
galleryNav.appendChild(navDot);
});
// Hide loading overlay
loadingOverlay.style.display = 'none';
// Set initial active state
updateNavDots();
// Start auto-sliding
startSlideShow();
}
// Start auto-sliding
function startSlideShow() {
slideInterval = setInterval(nextSlide, slideDuration);
}
// Go to specific slide
function goToSlide(index) {
currentSlide = index;
updateSliderPosition();
updateNavDots();
}
// Go to next slide
function nextSlide() {
currentSlide = (currentSlide + 1) % imageFiles.length;
updateSliderPosition();
updateNavDots();
}
// Update slider position
function updateSliderPosition() {
const slideWidth = 100; // percentage
galleryTrack.style.transform = `translateX(-${currentSlide * slideWidth}%)`;
}
// Update navigation dots
function updateNavDots() {
const navDots = document.querySelectorAll('.nav-dot');
navDots.forEach((dot, index) => {
if (index === currentSlide) {
dot.classList.add('active');
} else {
dot.classList.remove('active');
}
});
}
// Touch events for mobile swipe
let touchStartX = 0;
let touchEndX = 0;
galleryTrack.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, { passive: true });
galleryTrack.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
}, { passive: true });
function handleSwipe() {
const threshold = 50; // minimum swipe distance
if (touchEndX < touchStartX - threshold) {
// Swipe left - next slide
nextSlide();
} else if (touchEndX > touchStartX + threshold) {
// Swipe right - previous slide
currentSlide = (currentSlide - 1 + imageFiles.length) % imageFiles.length;
updateSliderPosition();
updateNavDots();
}
}
// Initialize the gallery
initGallery();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vishnumeher/mem" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>