react framer-motion 하나씩 뜨는 map

해적왕·2022년 7월 15일
0
post-thumbnail
post-custom-banner

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을 넣어주면 된다.

profile
프론트엔드
post-custom-banner

0개의 댓글