yarn add framer-motion
import { AnimatePresence } from 'framer-motion';
import { useLocation } from 'react-router-dom';
function App() {
const location = useLocation();
return (
<AnimatePresence exitBeforeEnter>
<Contain>
<Routes location={location} key={location.pathname}>
<Route path="/" element={<Ship/>} />
</Routes>
</Contain>
</AnimatePresence>
);
}
AnimatePresence
를 사용하면 구성 요소가 React 트리에서 제거될 때 애니메이션을 수행할 수 있다.
exitBeforeEnter
는 새로운 컴포넌트가 나타나 직전의 이전 컴포넌트가 사라지게 한다.
이걸 사용해야 exit, 즉 페이지에서 나갈 때 hide
로 설정한 부분이 나온다. 위 이미지를 보면 item을 선택했을 때 목록들이 아래로 내려가는 것을 볼 수 있다.
Data.js 안에 img,id,name을 넣어준다.
예시 )
export const Data = [
{
id: 1,
name: "tesla model 3",
img:""
},
{
id: 2,
name: "tesla model 4",
img:""
},
]
Ship.js
import { motion } from 'framer-motion';
import styled from 'styled-components';
import { Data } from './Data';
import { Link } from "react-router-dom";
const gridAnimation = {
show: {
transition: { staggerChildren: 0.1 }
},
hide: {
transition: { staggerChildren: 0.1, staggerDirection: -1 }
},
}
const imgAnimation = {
show: {
y: [200, 0],
opacity: [0, 1],
scale: [0.95, 1]
},
hide: {
y: [0, 200],
opacity: [1, 0],
scale: [1, 0.95]
},
}
const Ship = () => {
return (
<ShipContainer>
<ShipWrap
variants={gridAnimation}
animate="show"
exit="hide"
>
{Data.map((item) => {
return (
<Link to={`/ship/${item.id}`} key={item.id}>
<ImgWrap
variants={imgAnimation}>
<img src={item.img} />
<span>{item.name}</span>
</ImgWrap>
</Link>
)
})}
</CarsWrap>
</CarsContainer>
)
}
export default Ship;
const ShipContainer = styled.div`
max-width:1000px;
margin:0 auto;
`
const ShipWrap = styled(motion.div)`
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 20px;
grid-row-gap: 20px;
padding: 80px 0;
`
const ImgWrap = styled(motion.div)`
height: 250px;
display:flex;
align-items:center;
justify-content:center;
position:relative;
width: 90%;
img {
width: 90%;
max-height: 75%;
margin-top: 10%;
transition:0.8s;
}
`
목록을 motion.div로 감싸서 gridAnimation
을 넣어주면 되고
item
을 감싸서 imgAnimation
을 넣어주면 된다.