From 964223eb4c88312aa241daeef058de428f954727 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 17:01:56 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=BA=90=EC=8A=A4=ED=8D=BC=20=EB=B4=87?= =?UTF-8?q?=20=EA=B0=9C=EC=88=98=EC=97=90=20=EB=94=B0=EB=A5=B8=20UI=20?= =?UTF-8?q?=EB=B6=84=EA=B8=B0=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/CasperShowCase/CasperCards.tsx | 13 ++++- .../CasperShowCase/TransitionCasperCards.tsx | 51 +++++++++++++------ client/src/pages/CasperShowCase/index.tsx | 34 +++++++++---- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/client/src/features/CasperShowCase/CasperCards.tsx b/client/src/features/CasperShowCase/CasperCards.tsx index d1a1cdde..58d8707b 100644 --- a/client/src/features/CasperShowCase/CasperCards.tsx +++ b/client/src/features/CasperShowCase/CasperCards.tsx @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CasperCardType, TransitionCasperCards } from "./TransitionCasperCards"; @@ -8,8 +9,16 @@ interface CasperCardsProps { export function CasperCards({ cardList }: CasperCardsProps) { const cardLength = cardList.length; const cardLengthHalf = Math.floor(cardLength / 2); - const topCardList = cardList.slice(0, cardLengthHalf); - const bottomCardList = cardList.slice(cardLengthHalf, cardLength); + const visibleCardCount = useMemo(() => { + const width = window.innerWidth; + const cardWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; + + return Math.ceil(width / cardWidth); + }, []); + const isMultipleLine = visibleCardCount * 2 <= cardLength; + + const topCardList = cardList.slice(0, isMultipleLine ? cardLengthHalf : cardLength); + const bottomCardList = isMultipleLine ? cardList.slice(cardLengthHalf, cardLength) : []; const itemWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; const gap = 40; diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index 6373f931..a441b0c7 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { AnimatePresence, motion, useAnimation } from "framer-motion"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase"; @@ -29,6 +29,14 @@ export function TransitionCasperCards({ gap, isEndCard, }: TransitionCasperCardsProps) { + const visibleCardCount = useMemo(() => { + const width = window.innerWidth; + const cardWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; + + return Math.ceil(width / cardWidth); + }, []); + const isAnimated = visibleCardCount <= cardList.length; + const containerRef = useRef(null); const transitionControls = useAnimation(); @@ -54,6 +62,14 @@ export function TransitionCasperCards({ startAnimation(x); }, [transitionControls, totalWidth]); + const expandedCardList = useMemo(() => { + if (isAnimated) { + return [...cardList, ...cardList.slice(0, visibleCardCount)]; + } + + return cardList; + }, [cardList]); + const renderCardItem = (cardItem: CasperCardType, id: string) => { const [isFlipped, setIsFlipped] = useState(false); const { isInView, cardRef } = useLazyLoading(); @@ -92,20 +108,25 @@ export function TransitionCasperCards({ return ( - { - if (isEndCard(parseInt(String(latest.x)))) { - startAnimation(initialX); - } - }} - > - {cardList.map((card) => renderCardItem(card, `${card.id}`))} - {cardList.map((card) => renderCardItem(card, `${card.id}-clone`))} - + {isAnimated ? ( + { + if (isEndCard(parseInt(String(latest.x)))) { + startAnimation(initialX); + } + }} + > + {expandedCardList.map((card, idx) => renderCardItem(card, `${card.id}-${idx}`))} + + ) : ( +
    + {expandedCardList.map((card, idx) => renderCardItem(card, `${card.id}-${idx}`))} +
+ )}
); } diff --git a/client/src/pages/CasperShowCase/index.tsx b/client/src/pages/CasperShowCase/index.tsx index e3816ff9..0c98833a 100644 --- a/client/src/pages/CasperShowCase/index.tsx +++ b/client/src/pages/CasperShowCase/index.tsx @@ -79,16 +79,32 @@ export default function CasperShowCase() { id={CASPER_SHOWCASE_SECTIONS.SHOWCASE} className="flex flex-col justify-center items-center gap-800 w-full h-screen bg-n-neutral-950 overflow-hidden pt-1000" > - -

- 카드 위에 커서를 올리면 기대평을 볼 수 있어요 -

+ {cardListData.length === 0 ? ( + +

+ 나만의 캐스퍼 일렉트릭 봇을 만들어주세요! +

+ 캐스퍼 봇 아이콘 +
+ ) : ( + +

+ 카드 위에 커서를 올리면 기대평을 볼 수 있어요 +

- -
+ +
+ )}