From a31bf83b889be280ae610f3849758f46c617081e Mon Sep 17 00:00:00 2001 From: sunminnnnn Date: Fri, 13 Dec 2024 01:23:54 +0900 Subject: [PATCH] =?UTF-8?q?hotfix:=20PP=20main=20page=20artworkslider=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PromotionPage/Main/ArtworkList.tsx | 4 +- .../PromotionPage/Main/ArtworkSlider.tsx | 147 ++++++++++-------- src/pages/PromotionPage/Main/MainPage.tsx | 4 +- 3 files changed, 86 insertions(+), 69 deletions(-) diff --git a/src/components/PromotionPage/Main/ArtworkList.tsx b/src/components/PromotionPage/Main/ArtworkList.tsx index 1a6bda0..ac5b512 100644 --- a/src/components/PromotionPage/Main/ArtworkList.tsx +++ b/src/components/PromotionPage/Main/ArtworkList.tsx @@ -4,6 +4,7 @@ import { motion, Variants } from 'framer-motion'; import styled from 'styled-components'; import ArtworkNav from './ArtworkNav'; import { theme } from '@/styles/theme'; +import useWindowSize from '@/hooks/useWindowSize'; const defaultMainImg = lazy(() => import('@/assets/images/PP/defaultMainImg.jpg')); const SkeletonComponent = lazy(() => import('../SkeletonComponent/SkeletonComponent')); @@ -23,6 +24,7 @@ interface SectionProps { } const ArtworkList = React.forwardRef(({ index, data, count, scrollToSection }, ref) => { + const { width } = useWindowSize(); const MotionBox = motion(Box); const cardInView: Variants = { offscreen: { @@ -72,7 +74,7 @@ const ArtworkList = React.forwardRef(({ index, data, {data.title.length > 20 ? `${data.title.slice(0, 20)}...` : data.title} {data.overview} - + {width > 767 && } diff --git a/src/components/PromotionPage/Main/ArtworkSlider.tsx b/src/components/PromotionPage/Main/ArtworkSlider.tsx index 590017d..7c11946 100644 --- a/src/components/PromotionPage/Main/ArtworkSlider.tsx +++ b/src/components/PromotionPage/Main/ArtworkSlider.tsx @@ -1,37 +1,72 @@ -import React, { useState, useEffect, useRef, lazy } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import ArtworkList from './ArtworkList'; import { IArtwork } from '@/types/PromotionPage/artwork'; import { ARTWORKLIST_DATA } from '@/constants/introdutionConstants'; -import defaultMainImg from '@/assets/images/PP/defaultMainImg.jpg'; // 디폴트 이미지 임포트 - +import defaultMainImg from '@/assets/images/PP/defaultMainImg.jpg'; interface IArtworkSliderProps { artworks: IArtwork[]; } const ArtworkSlider: React.FC = ({ artworks }) => { - const [activeIndex, setActiveIndex] = useState(0); - const [transitioning, setTransitioning] = useState(false); - const activeIndexRef = useRef(0); + const [activeIndex, setActiveIndex] = useState(1); // 중간에서 시작 + const [isAnimating, setIsAnimating] = useState(false); + const sliderRef = useRef(null); + + // 앞뒤로 복사된 배열 생성 + const extendedArtworks = [ + artworks[artworks.length - 1], // 마지막 이미지 복사 + ...artworks, + artworks[0], // 첫 번째 이미지 복사 + ]; useEffect(() => { if (!artworks || artworks.length <= 1) return; const interval = setInterval(() => { - setTransitioning(true); - - activeIndexRef.current = (activeIndexRef.current + 1) % artworks.length; - - // 0.2초 후 activeIndex 교체 -> 바꿀 준비 완 - setTimeout(() => { - setActiveIndex(activeIndexRef.current); - setTransitioning(false); - }, 200); - }, 3000); + handleSlide(1); // 다음 슬라이드로 이동 + }, 4000); return () => clearInterval(interval); }, [artworks]); + const handleSlide = (direction: number) => { + if (isAnimating) return; + setIsAnimating(true); + + setTimeout(() => { + setActiveIndex((prevIndex) => prevIndex + direction); + }, 1000); // 애니메이션 시간과 동기화 + }; + +useEffect(() => { + const totalArtworks = artworks.length; + + if (activeIndex === 0) { + // 첫 번째 복사본에서 실제 마지막 이미지로 이동 + setTimeout(() => { + if (sliderRef.current) { + sliderRef.current.style.transition = 'none'; // 애니메이션 없이 이동 + } + setActiveIndex(totalArtworks); // 마지막으로 이동 + }, 1000); // 애니메이션 끝날 때까지 대기 + } else if (activeIndex === totalArtworks + 1) { + // 마지막 복사본에서 실제 첫 번째 이미지로 이동 + setActiveIndex(1); // 첫 번째 인덱스로 이동 + + // 애니메이션을 다시 활성화 + setTimeout(() => { + if (sliderRef.current) { + sliderRef.current.style.transition = 'transform 1s ease'; // 애니메이션 다시 활성화 + } + }, 50); // 아주 짧은 시간 후 애니메이션을 활성화 + } else { + if (sliderRef.current) { + sliderRef.current.style.transition = 'transform 1s ease'; // 일반 애니메이션 + } + } +}, [activeIndex, artworks.length]); + if (!artworks || artworks.length === 0) { return (
@@ -45,7 +80,7 @@ const ArtworkSlider: React.FC = ({ artworks }) => { link: '', }} count={1} - scrollToSection={() => { }} + scrollToSection={() => {}} elementHeight={window.innerHeight} index={0} /> @@ -84,61 +119,41 @@ const ArtworkSlider: React.FC = ({ artworks }) => { }} >
- { }} - elementHeight={window.innerHeight} - index={activeIndex} - /> -
- -
- { }} - elementHeight={window.innerHeight} - index={(activeIndex + 1) % artworks.length} - /> + {extendedArtworks.map((artwork, index) => ( +
+ {}} + elementHeight={window.innerHeight} + index={index} + /> +
+ ))}
); }; export default ArtworkSlider; - diff --git a/src/pages/PromotionPage/Main/MainPage.tsx b/src/pages/PromotionPage/Main/MainPage.tsx index 3061183..d8cd2bc 100644 --- a/src/pages/PromotionPage/Main/MainPage.tsx +++ b/src/pages/PromotionPage/Main/MainPage.tsx @@ -29,7 +29,7 @@ const MainPage = () => { const sectionsRef = useRef([]); const filteredMainData = data?.data ? data.data.filter((i) => i.projectType === 'main') : []; const filteredTopData = data?.data ? data.data.filter((i) => i.projectType === 'top') : []; - const { height } = useWindowSize(); + const { width, height } = useWindowSize(); const scrollToSection = useCallback((index: number) => { if (sectionsRef.current[index]) { @@ -129,7 +129,7 @@ const MainPage = () => { > {isLoading ? (
데이터 로딩 중...
- ) : height <= 915 ? ( + ) : width<=767 ? ( ({ id: item.id,