Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Image Gallery SPA</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> | |
.fade-in { | |
animation: fadeIn 0.3s ease-in-out; | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
.grid-btn { | |
aspect-ratio: 1/1; | |
transition: all 0.2s ease; | |
} | |
.grid-btn:hover { | |
transform: scale(1.05); | |
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |
} | |
.fullscreen-image { | |
background-size: contain; | |
background-repeat: no-repeat; | |
background-position: center; | |
background-color: rgba(0, 0, 0, 0.9); | |
} | |
.start-btn { | |
transition: all 0.3s ease; | |
} | |
.start-btn:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); | |
} | |
/* Custom scrollbar for grid */ | |
.grid-container { | |
scrollbar-width: thin; | |
scrollbar-color: #3b82f6 #e5e7eb; | |
} | |
.grid-container::-webkit-scrollbar { | |
width: 8px; | |
height: 8px; | |
} | |
.grid-container::-webkit-scrollbar-track { | |
background: #e5e7eb; | |
border-radius: 4px; | |
} | |
.grid-container::-webkit-scrollbar-thumb { | |
background-color: #3b82f6; | |
border-radius: 4px; | |
} | |
/* Ensure buttons fit viewport */ | |
.responsive-grid { | |
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); | |
} | |
@media (min-width: 640px) { | |
.responsive-grid { | |
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); | |
} | |
} | |
@media (min-width: 1024px) { | |
.responsive-grid { | |
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); | |
} | |
} | |
/* Navigation buttons */ | |
.nav-btn { | |
position: fixed; | |
z-index: 60; | |
padding: 12px; | |
background-color: rgba(0, 0, 0, 0.7); | |
color: white; | |
border-radius: 50%; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.nav-btn:hover { | |
background-color: rgba(0, 0, 0, 0.9); | |
transform: scale(1.1); | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 min-h-screen"> | |
<div class="container mx-auto px-4 py-8"> | |
<!-- Input Section --> | |
<div id="input-section" class="max-w-3xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8 fade-in"> | |
<h1 class="text-3xl font-bold text-gray-800 mb-6 text-center">Image Gallery</h1> | |
<div class="mb-6"> | |
<label for="image-urls" class="block text-sm font-medium text-gray-700 mb-2"> | |
Enter image URLs (one per line): | |
</label> | |
<textarea | |
id="image-urls" | |
rows="8" | |
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" | |
placeholder="https://example.com/image1.jpg https://example.com/image2.jpg https://example.com/image3.jpg"></textarea> | |
</div> | |
<div class="flex justify-center"> | |
<button | |
id="submit-btn" | |
class="px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors"> | |
<i class="fas fa-images mr-2"></i> Create Gallery | |
</button> | |
</div> | |
</div> | |
<!-- Cover Screen --> | |
<div id="cover-screen" class="hidden fixed inset-0 z-50 bg-black bg-opacity-90 flex flex-col items-center justify-center fade-in"> | |
<div id="cover-image" class="w-full h-full fullscreen-image"></div> | |
<button | |
id="start-btn" | |
class="absolute px-8 py-4 bg-blue-600 text-white text-xl font-bold rounded-full start-btn hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"> | |
START! <i class="fas fa-play ml-2"></i> | |
</button> | |
</div> | |
<!-- Grid Screen --> | |
<div id="grid-screen" class="hidden fixed inset-0 z-40 bg-gray-100 overflow-y-auto p-4 fade-in"> | |
<div class="container mx-auto max-w-6xl"> | |
<div class="flex justify-between items-center mb-6"> | |
<button id="back-to-cover-btn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"> | |
<i class="fas fa-arrow-left mr-2"></i> Back to Cover | |
</button> | |
<h2 class="text-2xl font-bold text-gray-800">Select an Image</h2> | |
<div class="w-32"></div> <!-- Spacer for balance --> | |
</div> | |
<div id="grid-container" class="grid-container responsive-grid grid gap-4 overflow-y-auto max-h-[80vh] p-2"></div> | |
</div> | |
</div> | |
<!-- Image Viewer --> | |
<div id="image-viewer" class="hidden fixed inset-0 z-50 bg-black bg-opacity-90 fade-in"> | |
<div id="viewer-image" class="w-full h-full fullscreen-image"></div> | |
<div id="image-number" class="absolute top-4 left-4 bg-black bg-opacity-70 text-white px-4 py-2 rounded-full text-xl font-bold"></div> | |
<button id="back-to-grid-btn" class="nav-btn" style="top: 20px; right: 20px;"> | |
<i class="fas fa-th-large text-xl"></i> | |
</button> | |
<button id="back-to-cover-btn-2" class="nav-btn" style="top: 80px; right: 20px;"> | |
<i class="fas fa-home text-xl"></i> | |
</button> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// DOM Elements | |
const inputSection = document.getElementById('input-section'); | |
const coverScreen = document.getElementById('cover-screen'); | |
const gridScreen = document.getElementById('grid-screen'); | |
const imageViewer = document.getElementById('image-viewer'); | |
const imageUrlsTextarea = document.getElementById('image-urls'); | |
const submitBtn = document.getElementById('submit-btn'); | |
const startBtn = document.getElementById('start-btn'); | |
const gridContainer = document.getElementById('grid-container'); | |
const coverImage = document.getElementById('cover-image'); | |
const viewerImage = document.getElementById('viewer-image'); | |
const imageNumber = document.getElementById('image-number'); | |
const backToCoverBtn = document.getElementById('back-to-cover-btn'); | |
const backToCoverBtn2 = document.getElementById('back-to-cover-btn-2'); | |
const backToGridBtn = document.getElementById('back-to-grid-btn'); | |
// Variables | |
let imageUrls = []; | |
// Event Listeners | |
submitBtn.addEventListener('click', handleSubmit); | |
startBtn.addEventListener('click', showGridScreen); | |
imageViewer.addEventListener('click', showGridScreen); | |
backToCoverBtn.addEventListener('click', showCoverScreen); | |
backToCoverBtn2.addEventListener('click', showCoverScreen); | |
backToGridBtn.addEventListener('click', showGridScreen); | |
// Functions | |
function handleSubmit() { | |
const urls = imageUrlsTextarea.value.trim().split('\n').filter(url => url.trim() !== ''); | |
if (urls.length < 2) { | |
alert('Please enter at least 2 image URLs (one for cover and at least one for the gallery)'); | |
return; | |
} | |
imageUrls = urls; | |
// Set cover image | |
coverImage.style.backgroundImage = `url('${imageUrls[0]}')`; | |
// Hide input section and show cover screen | |
inputSection.classList.add('hidden'); | |
coverScreen.classList.remove('hidden'); | |
// Create grid buttons | |
createGridButtons(); | |
} | |
function createGridButtons() { | |
gridContainer.innerHTML = ''; | |
for (let i = 1; i < imageUrls.length; i++) { | |
const btn = document.createElement('button'); | |
btn.className = 'grid-btn bg-blue-100 hover:bg-blue-200 rounded-lg shadow-md flex items-center justify-center transition-colors'; | |
btn.innerHTML = ` | |
<span class="text-blue-800 text-2xl font-bold">${i}</span> | |
`; | |
btn.addEventListener('click', () => showImage(i)); | |
gridContainer.appendChild(btn); | |
} | |
} | |
function showCoverScreen() { | |
coverScreen.classList.remove('hidden'); | |
gridScreen.classList.add('hidden'); | |
imageViewer.classList.add('hidden'); | |
} | |
function showGridScreen() { | |
coverScreen.classList.add('hidden'); | |
imageViewer.classList.add('hidden'); | |
gridScreen.classList.remove('hidden'); | |
} | |
function showImage(index) { | |
gridScreen.classList.add('hidden'); | |
viewerImage.style.backgroundImage = `url('${imageUrls[index]}')`; | |
imageNumber.textContent = index; | |
imageViewer.classList.remove('hidden'); | |
} | |
// Handle Enter key in textarea | |
imageUrlsTextarea.addEventListener('keydown', function(e) { | |
if (e.key === 'Enter' && e.ctrlKey) { | |
handleSubmit(); | |
} | |
}); | |
}); | |
</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=josejuan314/bingoimage" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> | |
</html> |