마우스 오버시 로딩바 애니메이션 추가

This commit is contained in:
2026-05-14 11:47:33 +09:00
parent c09227facc
commit 190e9aa151
2 changed files with 97 additions and 9 deletions
+63 -9
View File
@@ -1,9 +1,14 @@
const DELAY = 1000;
let _el = null;
let _imgEl = null;
let _timer = null;
let _visible = false;
const SVG_NS = 'http://www.w3.org/2000/svg';
const RADIUS = 20;
const CIRC = 2 * Math.PI * RADIUS; // ~125.66
let _el = null;
let _imgEl = null;
let _timer = null;
let _visible = false;
let _loaderEl = null;
export function init() {
_el = document.createElement('div');
@@ -22,7 +27,10 @@ export function setupCard(card) {
function _onEnter() {
const card = this;
clearTimeout(_timer);
_showLoader(card);
_timer = setTimeout(() => {
_removeLoader();
const thumb = card.querySelector('img.card-thumb');
if (!thumb) return;
_imgEl.src = thumb.src;
@@ -35,12 +43,60 @@ function _onLeave() {
clearTimeout(_timer);
_timer = null;
_visible = false;
_el.style.display = 'none';
_el.style.visibility = 'hidden';
_removeLoader();
_el.style.display = 'none';
_el.style.visibility = 'hidden';
}
// ── 원형 로딩바 ──────────────────────────────────
function _showLoader(card) {
_removeLoader();
const svg = document.createElementNS(SVG_NS, 'svg');
svg.classList.add('card-hover-loader');
svg.setAttribute('viewBox', '0 0 48 48');
// 배경 원
const bg = document.createElementNS(SVG_NS, 'circle');
bg.classList.add('loader-bg');
bg.setAttribute('cx', '24');
bg.setAttribute('cy', '24');
bg.setAttribute('r', '24');
// 트랙 링
const track = document.createElementNS(SVG_NS, 'circle');
track.classList.add('loader-track');
track.setAttribute('cx', '24');
track.setAttribute('cy', '24');
track.setAttribute('r', String(RADIUS));
// 진행 호
const progress = document.createElementNS(SVG_NS, 'circle');
progress.classList.add('loader-progress');
progress.setAttribute('cx', '24');
progress.setAttribute('cy', '24');
progress.setAttribute('r', String(RADIUS));
progress.style.strokeDasharray = CIRC;
progress.style.strokeDashoffset = CIRC;
svg.appendChild(bg);
svg.appendChild(track);
svg.appendChild(progress);
card.appendChild(svg);
_loaderEl = svg;
}
function _removeLoader() {
if (_loaderEl) {
_loaderEl.remove();
_loaderEl = null;
}
}
// ── 이미지 팝업 ──────────────────────────────────
function _show(card) {
// 위치 계산 전 화면 밖에 렌더링해서 실제 크기를 측정
_el.style.display = 'block';
_el.style.visibility = 'hidden';
_el.style.left = '0px';
@@ -55,14 +111,12 @@ function _show(card) {
const vh = window.innerHeight;
const gap = 16;
// 가로: 카드 오른쪽 우선, 공간 부족 시 왼쪽
let left = cardRect.right + gap;
if (left + popup.width > vw - 8) {
left = cardRect.left - popup.width - gap;
}
left = Math.max(8, Math.min(left, vw - popup.width - 8));
// 세로: 카드와 중앙 정렬, 화면 경계 클램프
let top = cardRect.top + (cardRect.height - popup.height) / 2;
top = Math.max(8, Math.min(top, vh - popup.height - 8));