diff --git a/css/gallery.css b/css/gallery.css index 8521742..bd187b3 100644 --- a/css/gallery.css +++ b/css/gallery.css @@ -302,13 +302,39 @@ overflow: hidden; } -.panorama-preview { +.panorama-preview-image { width: 100%; height: 100%; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - position: relative; + object-fit: cover; + transition: var(--transition); +} + +.panorama-play-button { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 80px; + height: 80px; + background: rgba(255, 136, 0, 0.9); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: var(--font-2xl); + color: var(--text-white); + transition: var(--transition); + box-shadow: 0 8px 25px rgba(255, 136, 0, 0.3); + backdrop-filter: blur(10px); +} + +.panorama-play-button i { + margin-left: 3px; /* 플레이 아이콘 중앙 정렬 보정 */ +} + +.panorama-clickable:hover .panorama-play-button { + transform: translate(-50%, -50%) scale(1.1); + box-shadow: 0 12px 35px rgba(255, 136, 0, 0.4); } .panorama-controls { @@ -386,7 +412,7 @@ 20%, 80% { opacity: 1; } } -/* Pannellum 360도 이미지 전체화면 모달 */ +/* 개선된 360도 이미지 전체화면 모달 */ .panorama-modal { display: none; position: fixed; @@ -396,21 +422,48 @@ height: 100vh; background: rgba(0, 0, 0, 0.95); z-index: 2000; + cursor: grab; } .panorama-modal.active { - display: block; + display: flex; + align-items: center; + justify-content: center; +} + +.panorama-modal:active { + cursor: grabbing; } .panorama-modal-content { position: relative; - width: 100vw; - height: 100vh; + width: 90vw; + height: 70vh; + max-width: 1200px; + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5); } .panorama-modal-viewer { + position: relative; width: 100%; height: 100%; + overflow: hidden; + border-radius: var(--border-radius); + background: #000; +} + +.panorama-modal-image { + position: absolute; + top: 0; + left: 0; + height: 100%; + object-fit: cover; + transition: transform 0.1s ease-out; + will-change: transform; + user-select: none; + pointer-events: none; } .panorama-modal-controls { @@ -490,6 +543,31 @@ font-weight: bold; } +.panorama-modal-help-text { + position: absolute; + top: var(--spacing-xl); + right: var(--spacing-xl); + background: rgba(0, 0, 0, 0.9); + color: var(--text-white); + padding: var(--spacing-lg); + border-radius: var(--border-radius); + font-size: var(--font-sm); + max-width: 250px; + z-index: 10; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.1); + display: none; +} + +.panorama-modal-help-text p { + margin: 0 0 var(--spacing-xs) 0; +} + +.panorama-modal-help-text strong { + color: var(--primary-color); + font-size: var(--font-base); +} + .panorama-modal-help { position: absolute; top: var(--spacing-lg); diff --git a/gallery.html b/gallery.html index cd25683..d9d651d 100644 --- a/gallery.html +++ b/gallery.html @@ -40,8 +40,8 @@ - - + + @@ -132,9 +132,15 @@
-
-
클릭하여 360도로 보기
+ 밍글 스튜디오 360도 전경 - 커튼을 걷은 모습 +
클릭하여 360° VR로 체험하기
360° VR
+
+ +
스튜디오 전경 (커튼 열림)
@@ -145,9 +151,15 @@
-
-
클릭하여 360도로 보기
+ 밍글 스튜디오 360도 전경 - 커튼을 친 모습 +
클릭하여 360° VR로 체험하기
360° VR
+
+ +
스튜디오 전경 (커튼 닫힘)
@@ -159,7 +171,8 @@ - + + \ No newline at end of file diff --git a/js/gallery.js b/js/gallery.js index 9e2993c..89d75a9 100644 --- a/js/gallery.js +++ b/js/gallery.js @@ -6,7 +6,7 @@ document.addEventListener('DOMContentLoaded', function() { initGallery(); initLightbox(); initGalleryAnimations(); - initPannellumViewers(); + initPhotoSphereViewers(); }); // 갤러리 초기화 @@ -267,33 +267,29 @@ function handleSwipe() { } // ======================================== -// Pannellum 기반 360도 이미지 뷰어 기능 +// Photo Sphere Viewer - 진짜 360도 VR 뷰어 // ======================================== -let currentPanoramaViewer = null; +let currentPhotoSphereViewer = null; -function initPannellumViewers() { +function initPhotoSphereViewers() { // 모달 생성 - createPannellumModal(); + createPhotoSphereModal(); - // 미리보기 이미지 설정 - initPanoramaPreviews(); + // 미리보기 설정 + initPhotoSpherePreviews(); } -function initPanoramaPreviews() { +function initPhotoSpherePreviews() { const containers = document.querySelectorAll('.panorama-clickable'); containers.forEach(container => { - const preview = container.querySelector('.panorama-preview'); const imageSrc = container.dataset.image; const title = container.dataset.title; - // 미리보기 이미지 설정 - preview.style.backgroundImage = `url('${imageSrc}')`; - - // 클릭 이벤트 - 전체화면 Pannellum 뷰어 열기 + // 클릭 이벤트 container.addEventListener('click', () => { - openPannellumModal(imageSrc, title); + openPhotoSphereModal(imageSrc, title); }); // 도움말 자동 숨김 @@ -307,159 +303,201 @@ function initPanoramaPreviews() { }); } -function createPannellumModal() { +function createPhotoSphereModal() { const modalHTML = ` -
+
-
+
-
+
- - - +
- +
+

360° VR 조작법

+

🖱️ 드래그: 전방향 회전

+

📱 터치: 터치 후 드래그

+

🖱️ 휠: 줌 인/아웃

+

📱 핀치: 줌 인/아웃

+

⌨️ 화살표: 방향 이동

+

⌨️ +/-: 줌 조절

+

⌨️ ESC: 닫기

+
`; document.body.insertAdjacentHTML('beforeend', modalHTML); - - // 모달 이벤트 리스너 설정 - setupPannellumModalListeners(); + setupPhotoSphereModalListeners(); } -function setupPannellumModalListeners() { - const modal = document.getElementById('pannellum-modal'); - const closeBtn = document.getElementById('pannellum-modal-close'); - const resetBtn = document.getElementById('pannellum-reset-btn'); - const autoBtn = document.getElementById('pannellum-auto-btn'); - const fullscreenBtn = document.getElementById('pannellum-fullscreen-btn'); +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', closePannellumModal); + // 모달 닫기 + closeBtn.addEventListener('click', closePhotoSphereModal); + modal.addEventListener('click', (e) => { + if (e.target === modal) closePhotoSphereModal(); + }); - // ESC 키로 모달 닫기 + // ESC 키 document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && modal.classList.contains('active')) { - closePannellumModal(); + closePhotoSphereModal(); } }); // 리셋 버튼 resetBtn.addEventListener('click', () => { - if (currentPanoramaViewer) { - currentPanoramaViewer.setPitch(0); - currentPanoramaViewer.setYaw(0); - stopAutoRotate(); + if (currentPhotoSphereViewer) { + currentPhotoSphereViewer.animate({ + yaw: 0, + pitch: 0, + zoom: 50, + speed: '2rpm' + }); } }); // 자동 회전 버튼 autoBtn.addEventListener('click', () => { - if (isAutoRotating) { - stopAutoRotate(); - } else { - startAutoRotate(); + 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 (currentPanoramaViewer) { - currentPanoramaViewer.toggleFullscreen(); + if (currentPhotoSphereViewer) { + currentPhotoSphereViewer.enterFullscreen(); } }); - function startAutoRotate() { - if (currentPanoramaViewer) { - currentPanoramaViewer.startAutoRotate(0.5); // 초당 0.5도 회전 - isAutoRotating = true; - autoBtn.innerHTML = ' 정지'; - autoBtn.classList.add('active'); - } - } + // 도움말 버튼 + helpBtn.addEventListener('click', () => { + helpVisible = !helpVisible; + helpText.style.display = helpVisible ? 'block' : 'none'; + helpBtn.classList.toggle('active', helpVisible); + }); - function stopAutoRotate() { - if (currentPanoramaViewer) { - currentPanoramaViewer.stopAutoRotate(); - isAutoRotating = false; - autoBtn.innerHTML = ' 자동회전'; - autoBtn.classList.remove('active'); - } - } + // 도움말 자동 숨김 + setTimeout(() => { + helpText.style.display = 'none'; + }, 6000); } -function openPannellumModal(imageSrc, title) { - const modal = document.getElementById('pannellum-modal'); - const modalTitle = document.getElementById('pannellum-modal-title'); +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'; - // Pannellum 뷰어 초기화 - currentPanoramaViewer = pannellum.viewer('pannellum-viewer', { - type: 'equirectangular', - panorama: imageSrc, - autoLoad: true, - autoRotate: 0, - compass: true, - northOffset: 0, - preview: imageSrc, - hfov: 100, - minHfov: 50, - maxHfov: 120, - pitch: 0, - yaw: 0, - mouseZoom: true, - keyboardZoom: true, - draggable: true, - disableKeyboardCtrl: false, - showControls: false, - showFullscreenCtrl: false, - showZoomCtrl: false, - hotSpotDebug: false, - backgroundColor: [0, 0, 0], - orientationOnByDefault: false - }); - - // 뷰어 로드 완료 이벤트 - currentPanoramaViewer.on('load', function() { - console.log('Pannellum 360도 뷰어 로드 완료'); - }); + // 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 closePannellumModal() { - const modal = document.getElementById('pannellum-modal'); - const autoBtn = document.getElementById('pannellum-auto-btn'); - - // 자동 회전 정지 - if (autoBtn.classList.contains('active')) { - autoBtn.click(); - } +function closePhotoSphereModal() { + const modal = document.getElementById('photosphere-modal'); + const autoBtn = document.getElementById('photosphere-auto-btn'); // 뷰어 정리 - if (currentPanoramaViewer) { - currentPanoramaViewer.destroy(); - currentPanoramaViewer = null; + if (currentPhotoSphereViewer) { + currentPhotoSphereViewer.destroy(); + currentPhotoSphereViewer = null; } + // 버튼 초기화 + autoBtn.innerHTML = ' 자동회전'; + autoBtn.classList.remove('active'); + modal.classList.remove('active'); document.body.style.overflow = ''; - // 뷰어 컨테이너 초기화 - document.getElementById('pannellum-viewer').innerHTML = ''; + // 컨테이너 정리 + document.getElementById('photosphere-viewer').innerHTML = ''; } \ No newline at end of file