fix: [academy] 방화셔터 이미지 hover 시 화면 중앙 대형 프리뷰 효과 구현
- 이미지 hover 시 350ms 후 화면 중앙에 80vh 크기로 확대 프리뷰 - backdrop blur 오버레이 + scale 애니메이션 효과 - 프리뷰 클릭 시 기존 라이트박스로 전환
This commit is contained in:
@@ -4,17 +4,66 @@
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
/* 이미지 기본 스타일 */
|
||||
.academy-img-hover {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
.academy-img-hover:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.academy-img-wrap {
|
||||
overflow: hidden;
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
/* hover 프리뷰 오버레이 */
|
||||
#hover-preview {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 45;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(3px);
|
||||
pointer-events: none;
|
||||
}
|
||||
#hover-preview.is-active {
|
||||
display: flex;
|
||||
pointer-events: auto;
|
||||
}
|
||||
#hover-preview img {
|
||||
max-height: 80vh;
|
||||
max-width: 85vw;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.5);
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
transition: opacity 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
#hover-preview.is-active img {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
#hover-preview .hover-caption {
|
||||
position: absolute;
|
||||
bottom: 2rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: rgba(255,255,255,0.85);
|
||||
font-size: 0.8rem;
|
||||
background: rgba(0,0,0,0.5);
|
||||
padding: 0.4rem 1rem;
|
||||
border-radius: 2rem;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease 0.15s;
|
||||
}
|
||||
#hover-preview.is-active .hover-caption {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 클릭 라이트박스 */
|
||||
#lightbox {
|
||||
display: none;
|
||||
position: fixed;
|
||||
@@ -22,7 +71,7 @@
|
||||
z-index: 50;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
#lightbox.is-open {
|
||||
@@ -1084,7 +1133,13 @@ class="rounded-lg cursor-pointer academy-img-hover"
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 이미지 라이트박스 -->
|
||||
<!-- hover 프리뷰 오버레이 -->
|
||||
<div id="hover-preview">
|
||||
<img id="hover-preview-img" src="" alt="">
|
||||
<span class="hover-caption" id="hover-preview-caption"></span>
|
||||
</div>
|
||||
|
||||
<!-- 클릭 라이트박스 -->
|
||||
<div id="lightbox" onclick="closeLightbox()">
|
||||
<button onclick="closeLightbox()" style="position:absolute; top:1rem; right:1rem; background:none; border:none; cursor:pointer; color:rgba(255,255,255,0.8); padding:0.5rem;">
|
||||
<svg style="width:2rem; height:2rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /></svg>
|
||||
@@ -1092,21 +1147,90 @@ class="rounded-lg cursor-pointer academy-img-hover"
|
||||
<img id="lightbox-img" onclick="event.stopPropagation()">
|
||||
</div>
|
||||
<script>
|
||||
function openLightbox(el) {
|
||||
var lb = document.getElementById('lightbox');
|
||||
var img = document.getElementById('lightbox-img');
|
||||
img.src = el.src;
|
||||
img.alt = el.alt;
|
||||
lb.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
function closeLightbox() {
|
||||
var lb = document.getElementById('lightbox');
|
||||
lb.classList.remove('is-open');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') closeLightbox();
|
||||
});
|
||||
(function() {
|
||||
var preview = document.getElementById('hover-preview');
|
||||
var previewImg = document.getElementById('hover-preview-img');
|
||||
var previewCaption = document.getElementById('hover-preview-caption');
|
||||
var hoverTimer = null;
|
||||
var isPreviewActive = false;
|
||||
var HOVER_DELAY = 350;
|
||||
|
||||
// 모든 academy 이미지에 hover 프리뷰 바인딩
|
||||
document.querySelectorAll('.academy-img-hover').forEach(function(img) {
|
||||
img.addEventListener('mouseenter', function() {
|
||||
var el = this;
|
||||
hoverTimer = setTimeout(function() {
|
||||
showPreview(el);
|
||||
}, HOVER_DELAY);
|
||||
});
|
||||
|
||||
img.addEventListener('mouseleave', function() {
|
||||
clearTimeout(hoverTimer);
|
||||
// 프리뷰가 활성화 된 상태가 아니면 아무것도 안함
|
||||
// 프리뷰 위에 마우스가 있으면 프리뷰가 유지됨
|
||||
if (!isPreviewActive) return;
|
||||
// 짧은 딜레이 후 마우스가 프리뷰 위에 없으면 닫기
|
||||
setTimeout(function() {
|
||||
if (!preview.matches(':hover')) {
|
||||
hidePreview();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
// 프리뷰 오버레이에서 마우스가 벗어나면 닫기
|
||||
preview.addEventListener('mouseleave', function() {
|
||||
hidePreview();
|
||||
});
|
||||
|
||||
// 프리뷰 클릭 시 라이트박스로 전환
|
||||
preview.addEventListener('click', function() {
|
||||
hidePreview();
|
||||
openLightbox(previewImg);
|
||||
});
|
||||
|
||||
function showPreview(el) {
|
||||
previewImg.src = el.src;
|
||||
previewImg.alt = el.alt || '';
|
||||
// 캡션: 이미지 다음 형제 p 태그 또는 alt 텍스트
|
||||
var caption = el.alt || '';
|
||||
var nextP = el.parentElement && el.parentElement.querySelector('p');
|
||||
if (nextP) caption = nextP.textContent;
|
||||
previewCaption.textContent = caption;
|
||||
|
||||
preview.classList.add('is-active');
|
||||
isPreviewActive = true;
|
||||
}
|
||||
|
||||
function hidePreview() {
|
||||
preview.classList.remove('is-active');
|
||||
isPreviewActive = false;
|
||||
}
|
||||
|
||||
// 클릭 라이트박스
|
||||
window.openLightbox = function(el) {
|
||||
var lb = document.getElementById('lightbox');
|
||||
var img = document.getElementById('lightbox-img');
|
||||
img.src = el.src;
|
||||
img.alt = el.alt;
|
||||
lb.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
// hover 프리뷰가 열려있으면 닫기
|
||||
hidePreview();
|
||||
};
|
||||
|
||||
window.closeLightbox = function() {
|
||||
var lb = document.getElementById('lightbox');
|
||||
lb.classList.remove('is-open');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
if (isPreviewActive) hidePreview();
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@endsection
|
||||
|
||||
Reference in New Issue
Block a user