일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- React
- tanstack query
- react router dom
- 토이프로젝트
- 자바스크립트
- Form
- reduxtoolkit
- 타입스크립트
- react pattern
- 리덕스
- tailwind
- 리액트 패턴
- 리액트 라우터 돔
- styled component
- 코어자바스크립트
- React Query
- 프론트엔드
- Next.js
- TypeScript
- 리액트
- JavaScript
- 토이 프로젝트
- Supabase
- revalidatepath
- 프로그래머스
- 그리디
- 스택
- 코테
- 동적계획법
- 코딩테스트
개발 블로그
Pokemon Card Flip - 7. Motion 라이브러리로 애니메이션 넣기 본문
Motion - A modern animation library for JavaScript and React
Motion is built on native browser APIs for a tiny filesize and superfast performance. It uses hardware acceleration for smooth and eco-friendly animations. Previously Framer Motion.
motion.dev
Motion이란?
React에서 부드러운 애니메이션을 쉽게 구현할 수 있도록 도와주는 라이브러리
애니메이션을 직접 CSS로 만들 필요 없이, 간단한 props만으로 자연스러운 모션 효과를 적용이 가능
물리 기반(Spring) 애니메이션을 지원해서, 더 부드럽고 자연스러운 움직임을 만들 수 있음
자동 언마운트 애니메이션 (exit + AnimatePresence) 기능이 있어서, 요소가 사라질 때도 애니메이션을 추가할수 있음
import { motion } from "framer-motion";
const SelectButton: React.FC<{
onMode: () => void;
children: React.ReactNode;
buttonColor: string;
}> = ({ onMode, children, buttonColor }) => {
return (
<motion.button
onClick={onMode}
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 30 }}
transition={{ type: "spring" }}
style={{ backgroundColor: buttonColor }}
className={
`bg-[${buttonColor}]` +
"px-4 py-2 text-lg font-bold text-white border-4 border-black shadow-[4px_4px_0px_black] active:shadow-none active:translate-x-1 active:translate-y-1 w-[180px] md:w-[250px] lg:w-[400px] lg:h-[90px] lg:text-3xl"
}
>
{children}
</motion.button>
);
};
export default SelectButton;
적용할 컴포넌트 이름앞에 motion.을 적어주면 적용이 가능하다
initial은 해당 컴포넌트가 최초 렌더링 될때 적용될 애니메이션이다
animate는 렌더링 후 적용될 애니메이션이다
exit는 컴포넌트가 DOM에서 사라질때 적용될 애니메이션이다 exit를 사용하기 위해서는 부모 컴포넌트를 AnimationPresence로 감싸줘야 적용이 가능하다
import "./App.css";
import Main from "./components/Main";
import SelectDifference from "./components/SelectDifference";
import { useAppSelector } from "./hooks/useAppSelector";
import AppWrapper from "./layout/AppWrapper";
import { selectMode } from "./slice/modeSlice";
import { AnimatePresence } from "framer-motion";
const App = () => {
const currentMode = useAppSelector(selectMode);
return (
<AppWrapper>
<AnimatePresence mode='wait'>
{currentMode === "main" && <Main />}
</AnimatePresence>
<AnimatePresence mode='wait'>
{currentMode === "selectDifference" && <SelectDifference />}
</AnimatePresence>
<AnimatePresence>
{currentMode === "game" && <div>게임화면입니다</div>}
</AnimatePresence>
{currentMode === "docs" && <div>도감화면입니다</div>}
</AppWrapper>
);
};
export default App;
현재 App.tsx에서 리덕스 툴킷으로 관리하고있는 currentMode값에따라 컴포넌트를 조건부로 렌더링한다
import SelectButton from "../ui/SelectButton";
import { useAppDispatch } from "../hooks/useAppDispatch";
import { setMode } from "../slice/modeSlice";
const Main = () => {
const dispatch = useAppDispatch();
const selectDifferenceButtonHandler = () => {
dispatch(setMode("selectDifference"));
};
const docsButtonHandler = () => {
dispatch(setMode("docs"));
};
return (
<div className='absolute bottom-[120px] left-1/2 -translate-x-1/2'>
<div className='flex flex-col gap-5'>
<SelectButton
onMode={selectDifferenceButtonHandler}
buttonColor='#181818'
>
게임시작
</SelectButton>
<SelectButton onMode={docsButtonHandler} buttonColor='#181818'>
도감보기
</SelectButton>
</div>
</div>
);
};
export default Main;
import SelectButton from "../ui/SelectButton";
import { useAppDispatch } from "../hooks/useAppDispatch";
import { setMode } from "../slice/modeSlice";
const SelectDifference = () => {
const dispatch = useAppDispatch();
const gameButtonHandler = () => {
dispatch(setMode("game"));
};
return (
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
<div className='flex flex-col gap-[80px]'>
<SelectButton buttonColor='#EF4444' onMode={gameButtonHandler}>
쉬움
</SelectButton>
<SelectButton buttonColor='#FACC15' onMode={gameButtonHandler}>
보통
</SelectButton>
<SelectButton buttonColor='#3B82F6' onMode={gameButtonHandler}>
어려움
</SelectButton>
</div>
</div>
);
};
export default SelectDifference;
'토이프로젝트 > Pokemon Card Flip' 카테고리의 다른 글
Pokemon Card Flip - 9.게임 보드 만들기(2) (0) | 2025.03.20 |
---|---|
Pokemon Card Flip - 8.게임 보드 만들기(1) (0) | 2025.03.20 |
Pokemon Card Flip - 6. tailwind 기본 폰트 설정 (0) | 2025.03.16 |
Pokemon Card Flip - 5. reduxToolkit을 이용한 앱 상태 관리 (0) | 2025.03.15 |
Pokemon Card Flip - 4.reduxTookit, tanstackquery 설치 (0) | 2025.03.15 |