- 카드 깜빡임 보완
- 모달 상태, 가격 표시 방법 수정
This commit is contained in:
2026-02-18 03:35:55 +09:00
parent bde819d1a1
commit cfd3fb8b75
6 changed files with 119 additions and 137 deletions

View File

@@ -8,6 +8,8 @@ import { scrollToImage } from './carousel.js';
console.log('Total products loaded:', productsData.length);
let lastThumbnailIndex = -1;
// HTML onclick에서 사용하기 위한 전역 등록
window.openModal = openModal;
window.closeModal = closeModal;
@@ -326,31 +328,32 @@ window.handleThumbnailHover = (e, productId) => {
}
};
// 페이드 업데이트 함수
/** * 썸네일을 즉시 업데이트하는 함수
* 페이드 애니메이션을 제거하여 반응성을 높이고 깜빡임을 방지합니다.
*/
function updateThumbnailWithFade(productId, newImageUrl, index) {
const mainThumb = document.getElementById(`thumb-${productId}`);
const fadeThumb = document.getElementById(`thumb-fade-${productId}`);
const indicator = document.getElementById(`indicator-${productId}`);
if (!mainThumb || !fadeThumb) return;
if (!mainThumb) return;
// 기존에 해당 카드에서 돌아가던 타이머가 있다면 즉시 제거
// 1. 기존 페이드 타이머가 있다면 즉시 제거 (충돌 방지)
if (fadeTimers[productId]) {
clearTimeout(fadeTimers[productId]);
delete fadeTimers[productId];
}
// 페이드 레이어 세팅
fadeThumb.style.transition = 'opacity 0.3s ease-in-out';
fadeThumb.style.backgroundImage = `url("${newImageUrl}")`;
fadeThumb.style.opacity = '1';
// 타이머 시작
fadeTimers[productId] = setTimeout(() => {
mainThumb.style.backgroundImage = `url("${newImageUrl}")`;
// 2. 페이드 레이어(뒷배경)는 즉시 숨기고 메인 이미지만 즉시 교체
// transition 없이 즉시 교체되도록 인라인 스타일로 제어합니다.
if (fadeThumb) {
fadeThumb.style.transition = 'none';
fadeThumb.style.opacity = '0';
delete fadeTimers[productId]; // 작업 완료 후 타이머 삭제
}, 300);
}
mainThumb.style.backgroundImage = `url("${newImageUrl}")`;
// 3. 인디케이터 UI 업데이트
if (indicator) updateIndicatorUI(indicator, index);
}
@@ -360,8 +363,9 @@ window.handleThumbnailLeave = (productId) => {
resetThumbnail(productId);
};
/** * 마우스가 나갔을 때 썸네일을 첫 번째 이미지로 복구하는 함수
*/
function resetThumbnail(productId) {
// 1. 진행 중인 모든 페이드 타이머 즉시 파괴
if (fadeTimers[productId]) {
clearTimeout(fadeTimers[productId]);
delete fadeTimers[productId];
@@ -374,21 +378,17 @@ function resetThumbnail(productId) {
const fadeThumb = document.getElementById(`thumb-fade-${productId}`);
const indicator = document.getElementById(`indicator-${productId}`);
if (mainThumb && fadeThumb) {
const firstImg = `url("${product.images[0]}")`;
// 2. 페이드 레이어를 즉시 숨김 (transition 방해 금지)
fadeThumb.style.transition = 'none';
fadeThumb.style.opacity = '0';
// 3. 두 레이어 모두 첫 번째 이미지로 강제 일치
mainThumb.style.backgroundImage = firstImg;
fadeThumb.style.backgroundImage = firstImg;
// 4. 다음 호버를 위해 트랜지션 복구
setTimeout(() => {
fadeThumb.style.transition = 'opacity 0.3s ease-in-out';
}, 50);
if (mainThumb) {
const firstImgUrl = `url("${product.images[0]}")`;
// 즉시 첫 번째 이미지로 복구
mainThumb.style.backgroundImage = firstImgUrl;
if (fadeThumb) {
fadeThumb.style.transition = 'none';
fadeThumb.style.opacity = '0';
fadeThumb.style.backgroundImage = firstImgUrl;
}
}
if (indicator) updateIndicatorUI(indicator, 0);
@@ -428,17 +428,24 @@ window.handleTouchMove = (e, productId) => {
}
if (isDragging) {
const product = productsData.find((p) => p.id === productId);
const step = cardWidth / product.images.length;
let index = Math.floor(Math.abs(diffX) / step);
index = Math.max(0, Math.min(product.images.length - 1, index));
// [수정 핵심] 인덱스가 이전과 같으면 함수를 종료하여 불필요한 리렌더링 방지
if (lastThumbnailIndex === index) return;
lastThumbnailIndex = index;
const mainThumb = document.getElementById(`thumb-${productId}`);
const fadeThumb = document.getElementById(`thumb-fade-${productId}`);
if (mainThumb && fadeThumb) {
// 드래그 중에는 페이드 없이 즉시 교체 (반응성 우선)
// [수정 핵심] 인덱스가 실제로 변했을 때만 스타일을 바꿉니다.
if (mainThumb && lastThumbnailIndex !== index) {
lastThumbnailIndex = index; // 새 인덱스 저장
mainThumb.style.backgroundImage = `url("${product.images[index]}")`;
fadeThumb.style.opacity = '0'; // 페이드 레이어 숨김
if (fadeThumb) fadeThumb.style.opacity = '0';
updateIndicator(productId, index);
}
}
@@ -452,6 +459,7 @@ window.handleTouchEnd = (e, productId) => {
} else {
resetThumbnail(productId); // 드래그 종료 시 확실한 리셋
}
lastThumbnailIndex = -1; // 초기화
isDragging = false;
};