라이브러리/framer-motion
[Framer] 프레이머 모션(Framer motion) 상태값 변화없음으로 인한 애니메이션 중단 버그 해결 방법
순코딩
2024. 1. 19. 09:50
// 슬롯텍스트 모션 컴포넌트
const SlotTextMotion = () => {
// 슬롯에 표시될 문자열을 담은 배열
const majorArray = [1,2,3,4,5,6,7,8,9,10];
// 현재 보여지고 있는 슬롯의 인덱스를 나타내는 상태 변수
const initNum=Math.floor(Math.random() * majorArray.length);
const [currentIndex, setCurrentIndex] = useState(initNum);
const [index,setIndex]=useState(1);//
// 애니메이션이 완료되면 호출되는 함수
const onAnimationComplete = async () => {
const randNum = Math.floor(Math.random() * majorArray.length);
//현재 인덱스(이전에 랜덤으로 뽑은 인덱스)와 현재 뽑은 랜덤 수가 같으면
//상태(state)변화가 없기 때문에 모션의 key값이 변하지 않고 재렌더링이 이루어지지 않아 애니메이션이 중단된다.
if(currentIndex===randNum){
await setCurrentIndex(randNum+1);
}
// 같지 않을 경우
else{
await setCurrentIndex(randNum);
}
};
// Framer motion 애니메이션에 필요한 속성값 객체
const slotVariants = {
initial: { rotateX: 0, y: 0, opacity: 1 }, // 초기 상태
animate: { rotateX: [-90, 0, 90], y: [20, 0, -20], opacity: [0, 1, 0] }, // 위로 올라온다
transition: { duration: 1.5, ease: "linear", times: [0, 0.5, 1] }, // initial 상태에서 animate 상태까지 도달하는 데에 걸리는 시간은 duration
};
return (
<>
{/* 애니메이션의 등장,퇴장 감지 / onAnimationComplete을 사용하려면 필요함 */}
<AnimatePresence>
{/* 애니메이션 박스 */}
<motion.div
key={currentIndex} // 현재 슬롯의 인덱스를 키로 사용하여 애니메이션 처리
variants={slotVariants}
initial={slotVariants.initial}
animate={slotVariants.animate}
transition={slotVariants.transition}
// 애니메이션이 완료될 때 호출되는 함수 지정
onAnimationComplete={onAnimationComplete}
>
{/* 슬롯 아이템 보이는 곳 */}
<SlotText style={{ color: "#72C6EF" }}>{majorArray[currentIndex]}</SlotText>
</motion.div>
</AnimatePresence>
</>
);
};