// ======================================== // Gallery 페이지 전용 JavaScript // ======================================== document.addEventListener('DOMContentLoaded', function() { initGallery(); initLightbox(); initGalleryAnimations(); initPhotoSphereViewers(); }); // 갤러리 초기화 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(); // 오른쪽으로 스와이프 = 이전 이미지 } } } // ======================================== // Photo Sphere Viewer - 진짜 360도 VR 뷰어 // ======================================== let currentPhotoSphereViewer = null; function initPhotoSphereViewers() { // 모달 생성 createPhotoSphereModal(); // 미리보기 설정 initPhotoSpherePreviews(); } function initPhotoSpherePreviews() { const containers = document.querySelectorAll('.panorama-clickable'); containers.forEach(container => { const imageSrc = container.dataset.image; const title = container.dataset.title; // 클릭 이벤트 container.addEventListener('click', () => { openPhotoSphereModal(imageSrc, title); }); // 도움말 자동 숨김 setTimeout(() => { const help = container.querySelector('.panorama-help'); if (help) { help.style.opacity = '0'; setTimeout(() => help.remove(), 1000); } }, 4000); }); } function createPhotoSphereModal() { const modalHTML = `

360° VR 조작법

🖱️ 드래그: 전방향 회전

📱 터치: 터치 후 드래그

🖱️ 휠: 줌 인/아웃

📱 핀치: 줌 인/아웃

⌨️ 화살표: 방향 이동

⌨️ +/-: 줌 조절

⌨️ ESC: 닫기

`; document.body.insertAdjacentHTML('beforeend', modalHTML); setupPhotoSphereModalListeners(); } function setupPhotoSphereModalListeners() { const modal = document.getElementById('photosphere-modal'); const closeBtn = document.getElementById('photosphere-modal-close'); const resetBtn = document.getElementById('photosphere-reset-btn'); const autoBtn = document.getElementById('photosphere-auto-btn'); const fullscreenBtn = document.getElementById('photosphere-fullscreen-btn'); const helpBtn = document.getElementById('photosphere-help-btn'); const helpText = document.getElementById('photosphere-help-text'); let isAutoRotating = false; let helpVisible = false; // 모달 닫기 closeBtn.addEventListener('click', closePhotoSphereModal); modal.addEventListener('click', (e) => { if (e.target === modal) closePhotoSphereModal(); }); // ESC 키 document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && modal.classList.contains('active')) { closePhotoSphereModal(); } }); // 리셋 버튼 resetBtn.addEventListener('click', () => { if (currentPhotoSphereViewer) { currentPhotoSphereViewer.animate({ yaw: 0, pitch: 0, zoom: 50, speed: '2rpm' }); } }); // 자동 회전 버튼 autoBtn.addEventListener('click', () => { if (currentPhotoSphereViewer) { if (isAutoRotating) { currentPhotoSphereViewer.stopAutorotate(); autoBtn.innerHTML = ' 자동회전'; autoBtn.classList.remove('active'); isAutoRotating = false; } else { currentPhotoSphereViewer.startAutorotate(); autoBtn.innerHTML = ' 정지'; autoBtn.classList.add('active'); isAutoRotating = true; } } }); // 전체화면 버튼 fullscreenBtn.addEventListener('click', () => { if (currentPhotoSphereViewer) { currentPhotoSphereViewer.enterFullscreen(); } }); // 도움말 버튼 helpBtn.addEventListener('click', () => { helpVisible = !helpVisible; helpText.style.display = helpVisible ? 'block' : 'none'; helpBtn.classList.toggle('active', helpVisible); }); // 도움말 자동 숨김 setTimeout(() => { helpText.style.display = 'none'; }, 6000); } function openPhotoSphereModal(imageSrc, title) { const modal = document.getElementById('photosphere-modal'); const modalTitle = document.getElementById('photosphere-modal-title'); const viewerContainer = document.getElementById('photosphere-viewer'); modalTitle.textContent = title; modal.classList.add('active'); document.body.style.overflow = 'hidden'; // Photo Sphere Viewer 생성 try { currentPhotoSphereViewer = new PhotoSphereViewer.Viewer({ container: viewerContainer, panorama: imageSrc, caption: title, loadingImg: imageSrc, // 로딩 중 미리보기 touchmoveTwoFingers: true, mousewheelCtrlKey: false, defaultYaw: 0, defaultPitch: 0, defaultZoomLvl: 50, minFov: 30, maxFov: 90, autorotateDelay: null, autorotateIdle: false, autorotateSpeed: '2rpm', fisheye: false, navbar: [ 'zoom', 'move', 'fullscreen', { title: '자동회전', content: '🔄', onClick: () => { const autoBtn = document.getElementById('photosphere-auto-btn'); autoBtn.click(); } } ] }); // 이벤트 리스너 currentPhotoSphereViewer.addEventListener('ready', () => { console.log('Photo Sphere Viewer 준비 완료'); }); currentPhotoSphereViewer.addEventListener('autorotate', () => { console.log('자동 회전 시작'); }); currentPhotoSphereViewer.addEventListener('autorotate-stop', () => { console.log('자동 회전 정지'); }); } catch (error) { console.error('Photo Sphere Viewer 초기화 실패:', error); alert('360도 뷰어를 로드할 수 없습니다. 페이지를 새로고침해주세요.'); } } function closePhotoSphereModal() { const modal = document.getElementById('photosphere-modal'); const autoBtn = document.getElementById('photosphere-auto-btn'); // 뷰어 정리 if (currentPhotoSphereViewer) { currentPhotoSphereViewer.destroy(); currentPhotoSphereViewer = null; } // 버튼 초기화 autoBtn.innerHTML = ' 자동회전'; autoBtn.classList.remove('active'); modal.classList.remove('active'); document.body.style.overflow = ''; // 컨테이너 정리 document.getElementById('photosphere-viewer').innerHTML = ''; }