Skip to content

Commit

Permalink
Merge pull request #177 from softeerbootcamp4th/fix/#176-transition
Browse files Browse the repository at this point in the history
[Fix] Transition 버벅임 문제 해결
  • Loading branch information
sooyeoniya authored Aug 20, 2024
2 parents 52031f0 + 8e6fb6c commit d250c3e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 49 deletions.
9 changes: 5 additions & 4 deletions client/src/features/CasperShowCase/CasperCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export function CasperCards({ cardList }: CasperCardsProps) {
const itemWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH;
const gap = 40;
const totalWidth = (itemWidth + gap) * visibleCardCount;
const paddedCasperWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH + gap;

const isEndTopCard = (latestX: number) => {
return latestX <= -totalWidth;
return latestX <= -paddedCasperWidth;
};
const isEndBottomCard = (latestX: number) => {
return latestX >= 0;
Expand All @@ -39,15 +40,15 @@ export function CasperCards({ cardList }: CasperCardsProps) {
initialX={0}
gap={gap}
diffX={-totalWidth}
visibleCardCount={visibleCardCount}
visibleCardCount={visibleCardCount + 1}
isEndCard={isEndTopCard}
/>
<TransitionCasperCards
cardList={bottomCardList}
initialX={-totalWidth}
initialX={-paddedCasperWidth}
gap={gap}
diffX={totalWidth}
visibleCardCount={visibleCardCount}
visibleCardCount={visibleCardCount + 1}
isEndCard={isEndBottomCard}
isReverseCards
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { useState } from "react";
import { memo, useState } from "react";
import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper";
import { CasperFlipCard } from "@/features/CasperCustom/CasperCard/CasperFlipCard";
import type { CasperCardType } from "@/types/casper";

interface TransitionCasperCardItemProps {
cardItem: CasperCardType;
id: string;
id: number;
stopAnimation?: () => void;
startAnimation?: () => void;
}

export function TransitionCasperCardItem({
export const TransitionCasperCardItem = memo(function TransitionCasperCardItem({
cardItem,
id,
stopAnimation,
Expand Down Expand Up @@ -41,4 +41,4 @@ export function TransitionCasperCardItem({
<CasperFlipCard card={cardItem} size={CASPER_SIZE_OPTION.SM} isFlipped={isFlipped} />
</li>
);
}
});
77 changes: 36 additions & 41 deletions client/src/features/CasperShowCase/TransitionCasperCards.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { AnimatePresence, type ResolvedValues, motion, useAnimation } from "framer-motion";
import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase";
import type { CasperCardType } from "@/types/casper";
Expand All @@ -24,19 +24,19 @@ export function TransitionCasperCards({
isReverseCards = false,
}: TransitionCasperCardsProps) {
const isAnimated = visibleCardCount <= cardList.length;
const expandedCardList = useMemo(() => [...cardList, ...cardList, ...cardList], [cardList]);

const containerRef = useRef<HTMLUListElement>(null);
const transitionControls = useAnimation();

const [x, setX] = useState<number>(initialX);
const [visibleCardListIdx, setVisibleCardListIdx] = useState(0);
const [visibleCardList, setVisibleCardList] = useState<CasperCardType[]>([]);
const [popCardIdx, setPopCardIdx] = useState(cardList.length - 1);

const startAnimation = useCallback(
(x: number) => {
transitionControls.start({
x: [x, x + diffX * 2],
transition: CARD_TRANSITION(visibleCardCount * 2),
x: [x, x + diffX],
transition: CARD_TRANSITION(visibleCardCount),
});
},
[visibleCardCount, transitionControls]
Expand All @@ -51,41 +51,40 @@ export function TransitionCasperCards({
}
}, [transitionControls, containerRef]);

const visibleCardList = useMemo(() => {
const list = expandedCardList.slice(
visibleCardListIdx,
visibleCardListIdx + visibleCardCount * 2
);
useEffect(() => {
const currentCardList = cardList.slice(0, visibleCardCount);
const sortedCards = isReverseCards ? currentCardList.reverse() : currentCardList;
setVisibleCardList(sortedCards);
startAnimation(x);
}, []);

if (isAnimated && isReverseCards) {
return list.reverse();
const updateVisibleCards = (prevCards: CasperCardType[]) => {
const updatedCards = [...prevCards];
const lastCardIdx = (popCardIdx + 1) % cardList.length;

if (isReverseCards) {
updatedCards.pop();
updatedCards.unshift(cardList[lastCardIdx]);
} else {
updatedCards.shift();
updatedCards.push(cardList[lastCardIdx]);
}

return isAnimated ? list : cardList;
}, [
isReverseCards,
expandedCardList,
cardList,
isAnimated,
visibleCardCount,
visibleCardListIdx,
]);
setPopCardIdx(lastCardIdx);

useEffect(() => {
startAnimation(x);
}, []);
return updatedCards;
};

const handleUpdateAnimation = (latest: ResolvedValues) => {
if (isEndCard(parseInt(String(latest.x)))) {
let nextIdx = visibleCardListIdx + visibleCardCount;
const currentX = parseInt(String(latest.x), 10);

// 만약 nextIdx가 cardList의 길이를 초과하면 배열의 처음부터 다시 index를 카운트하도록 함
if (nextIdx >= cardList.length) {
nextIdx = nextIdx % cardList.length;
}
if (isEndCard(currentX)) {
setVisibleCardList((prevCards) => {
const updatedCards = updateVisibleCards(prevCards);
return updatedCards;
});

setVisibleCardListIdx(nextIdx);
startAnimation(initialX);
startAnimation(isReverseCards ? initialX : initialX);
}
};

Expand All @@ -99,24 +98,20 @@ export function TransitionCasperCards({
style={{ gap: `${gap}px` }}
onUpdate={handleUpdateAnimation}
>
{visibleCardList.map((card, idx) => (
{visibleCardList.map((card) => (
<TransitionCasperCardItem
key={`${card.id}-${idx}`}
key={card.id}
cardItem={card}
id={`${card.id}-${idx}`}
id={card.id}
stopAnimation={stopAnimation}
startAnimation={() => startAnimation(x)}
/>
))}
</motion.ul>
) : (
<ul className="flex w-screen justify-center" style={{ gap: `${gap}px` }}>
{visibleCardList.map((card, idx) => (
<TransitionCasperCardItem
key={`${card.id}-${idx}`}
cardItem={card}
id={`${card.id}-${idx}`}
/>
{cardList.map((card) => (
<TransitionCasperCardItem key={card.id} cardItem={card} id={card.id} />
))}
</ul>
)}
Expand Down

0 comments on commit d250c3e

Please sign in to comment.