// ======================================== // Gallery 페이지 전용 JavaScript // ======================================== document.addEventListener('DOMContentLoaded', function() { initGallery(); initLightbox(); initGalleryAnimations(); }); // 갤러리 초기화 function initGallery() { const galleryItems = document.querySelectorAll('.gallery-item'); galleryItems.forEach((item, index) => { const img = item.querySelector('.gallery-img'); // 이미지 클릭 시 라이트박스 열기 img.addEventListener('click', () => openLightbox(index)); // 이미지 로딩 에러 처리 img.addEventListener('error', function() { this.src = 'images/placeholder.jpg'; this.alt = '이미지를 불러올 수 없습니다'; }); // 레이지 로딩 구현 if ('IntersectionObserver' in window) { const imageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src || img.src; img.classList.remove('lazy'); imageObserver.unobserve(img); } }); }); if (img.dataset.src) { imageObserver.observe(img); } } }); } // 라이트박스 기능 let currentImageIndex = 0; const galleryImages = document.querySelectorAll('.gallery-img'); function initLightbox() { // 라이트박스 HTML 생성 const lightboxHTML = ` `; document.body.insertAdjacentHTML('beforeend', lightboxHTML); // ESC 키로 라이트박스 닫기 document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeLightbox(); if (e.key === 'ArrowLeft') previousImage(); if (e.key === 'ArrowRight') nextImage(); }); // 배경 클릭으로 라이트박스 닫기 document.getElementById('lightbox').addEventListener('click', function(e) { if (e.target === this) closeLightbox(); }); } function openLightbox(index) { currentImageIndex = index; const lightbox = document.getElementById('lightbox'); const lightboxImg = document.getElementById('lightbox-img'); const lightboxCaption = document.getElementById('lightbox-caption'); const currentImg = galleryImages[index]; const caption = currentImg.closest('.gallery-item').querySelector('.gallery-caption'); lightboxImg.src = currentImg.src; lightboxImg.alt = currentImg.alt; lightboxCaption.textContent = caption ? caption.textContent : currentImg.alt; lightbox.classList.add('active'); document.body.style.overflow = 'hidden'; } function closeLightbox() { const lightbox = document.getElementById('lightbox'); lightbox.classList.remove('active'); document.body.style.overflow = ''; } function nextImage() { currentImageIndex = (currentImageIndex + 1) % galleryImages.length; openLightbox(currentImageIndex); } function previousImage() { currentImageIndex = (currentImageIndex - 1 + galleryImages.length) % galleryImages.length; openLightbox(currentImageIndex); } // 갤러리 애니메이션 function initGalleryAnimations() { const galleryItems = document.querySelectorAll('.gallery-item'); // Intersection Observer를 사용한 애니메이션 const observerOptions = { threshold: 0.1, rootMargin: '50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach((entry, index) => { if (entry.isIntersecting) { setTimeout(() => { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; }, index * 100); observer.unobserve(entry.target); } }); }, observerOptions); galleryItems.forEach(item => { item.style.opacity = '0'; item.style.transform = 'translateY(30px)'; item.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; observer.observe(item); }); } // 갤러리 필터 기능 (향후 확장용) function initGalleryFilters() { const filterButtons = document.querySelectorAll('.filter-btn'); const galleryItems = document.querySelectorAll('.gallery-item'); filterButtons.forEach(btn => { btn.addEventListener('click', function() { // 활성 버튼 업데이트 filterButtons.forEach(b => b.classList.remove('active')); this.classList.add('active'); const filter = this.dataset.filter; galleryItems.forEach(item => { if (filter === 'all' || item.dataset.category === filter) { item.style.display = 'block'; setTimeout(() => { item.style.opacity = '1'; item.style.transform = 'scale(1)'; }, 10); } else { item.style.opacity = '0'; item.style.transform = 'scale(0.8)'; setTimeout(() => { item.style.display = 'none'; }, 300); } }); }); }); } // 이미지 프리로딩 function preloadImages() { galleryImages.forEach(img => { const imagePreload = new Image(); imagePreload.src = img.src; }); } // 갤러리 검색 기능 (향후 확장용) function initGallerySearch() { const searchInput = document.getElementById('gallery-search'); const galleryItems = document.querySelectorAll('.gallery-item'); if (searchInput) { searchInput.addEventListener('input', function() { const searchTerm = this.value.toLowerCase(); galleryItems.forEach(item => { const caption = item.querySelector('.gallery-caption'); const alt = item.querySelector('.gallery-img').alt; const text = (caption ? caption.textContent : '') + ' ' + alt; if (text.toLowerCase().includes(searchTerm)) { item.style.display = 'block'; } else { item.style.display = 'none'; } }); }); } } // 이미지 로딩 상태 표시 function showGalleryLoading() { const loading = document.querySelector('.gallery-loading'); if (loading) { loading.style.display = 'block'; } } function hideGalleryLoading() { const loading = document.querySelector('.gallery-loading'); if (loading) { loading.style.display = 'none'; } } // 갤러리 그리드 리사이즈 최적화 let resizeTimeout; window.addEventListener('resize', function() { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(function() { // 갤러리 그리드 재조정 로직 const galleryGrid = document.querySelector('.gallery-grid'); if (galleryGrid) { galleryGrid.style.opacity = '0.8'; setTimeout(() => { galleryGrid.style.opacity = '1'; }, 100); } }, 250); }); // 터치 이벤트 지원 (모바일) let touchStartX = 0; let touchEndX = 0; document.addEventListener('touchstart', function(e) { if (document.getElementById('lightbox').classList.contains('active')) { touchStartX = e.changedTouches[0].screenX; } }); document.addEventListener('touchend', function(e) { if (document.getElementById('lightbox').classList.contains('active')) { touchEndX = e.changedTouches[0].screenX; handleSwipe(); } }); function handleSwipe() { const swipeThreshold = 50; const diff = touchStartX - touchEndX; if (Math.abs(diff) > swipeThreshold) { if (diff > 0) { nextImage(); // 왼쪽으로 스와이프 = 다음 이미지 } else { previousImage(); // 오른쪽으로 스와이프 = 이전 이미지 } } }