라이브러리 설치 및 기본 사용 법은 아래 링크에서 확인
https://cocococo.tistory.com/29
Share Layout Animation
레이아웃 공유 란?
서로 다른 애니메이션 효과를 자연스럽게 이어지도록 하는 방법이다.
1. Layout Animation ( CSS 변경을 통한 자동 애니메이션 적용 )
Layout에 prop을 사용한 애니메이션 적용 방법
Layout prop이란?
element에게 prop을 주어 CSS를 변경하게되면, 해당 element는 Layout이 바뀔 때 애니메이션 효과가 발생한다.
( CSS 때문에 Layout이 바뀐다면 저절로 애니메이션 효과가 이루어진다. )
function App() {
const [clicked, setClicked] = useState(false);
const toggleClicked = () => setClicked((prev) => !prev);
return (
<Wrapper onClick={toggleClicked}>
<Box
style={{
justifyContent: clicked ? "center" : "flex-start",
alignItems: clicked ? "center" : "flex-start",
}}
>
{/* 이동 되는 컴포넌트에 layout prop을 준다. */}
<Circle layout />
</Box>
</Wrapper>
);
}
export default App;
- Layout Prop만 넣어주면 motion이 감지해 애니메이션 효과를 자동으로 넣어준다.
2. Share Layout Animation ( 애니메이션 공유 )
서로 다은 애니메이션이 자연스럽게 이어지도록 공유하는 Layout 방법
* Source Code *
https://github.com/kangilbin/React.js/blob/master/animation/src/ShareLayoutAnimate.tsx
function App() {
const [clicked, setClicked] = useState(false);
const toggleClicked = () => setClicked((prev) => !prev);
return (
<Wrapper onClick={toggleClicked}>
<Box>{!clicked ? <Circle layoutId="circle" /> : null}</Box>
<Box>{clicked ? <Circle layoutId="circle" /> : null}</Box>
</Wrapper>
);
}
export default App;
- layoutId : 동일한 loyoutId를 사용하게 되면, Framer(애니메이션 라이브러리)에게 같은 컴포넌트라고 알려주어 서로 다른 컴포넌트의 애니메이션이 자연스럽게 이어진다.
2-1) Share Layout Animation 사용 예
* Source Code *
https://github.com/kangilbin/React.js/blob/master/animation/src/ShareLayout2.tsx
import { AnimatePresence, motion } from "framer-motion";
import styled from "styled-components";
import { useState } from "react";
const Wrapper = styled(motion.div)`
height: 100vh;
width: 100vw;
display: flex;
justify-content: space-around;
align-items: center;
`;
const Grid = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
width: 50vw;
gap: 10px;
div:first-child,
div:last-child {
grid-column: span 2;
}
`;
const Box = styled(motion.div)`
height: 200px;
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;
const Overlay = styled(motion.div)`
width: 100%;
height: 100%;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
`;
const OverlayVariants = {
initial: { backgroundColor: "rgba(0, 0, 0, 0)" },
animate: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
exit: { backgroundColor: "rgba(0, 0, 0, 0)" },
};
function App() {
// null 또는 string type이라고 정의
const [id, setId] = useState<null | string>(null);
return (
<Wrapper>
<Grid>
{["1", "2", "3", "4"].map((n) => (
// layoutId는 string이어야 한다.
<Box onClick={() => setId(n)} key={n} layoutId={n} />
))}
</Grid>
<AnimatePresence>
{id && (
<Overlay
onClick={() => setId(null)}
variants={OverlayVariants}
initial="initial"
animate="animate"
exit="exit"
>
{/* 모달 layoutId */}
<Box layoutId={id} style={{ width: 400, height: 200 }} />
</Overlay>
)}
</AnimatePresence>
</Wrapper>
);
}
export default App;
- 4개의 서로 다른 layoutId를 가진 컴포넌트를 만들고, 중앙의 모달 컴포넌트와 layoutId를 동일하게 바꿔어 주면서 자연스러운 애니메이션 효과를 만든다.
- layoutId는 Type String만 가능하다.
반응형
'React' 카테고리의 다른 글
[NextJS] 프로젝트 생성 및 실행 방법 (0) | 2022.10.12 |
---|---|
[NextJS] Pre-Rendering, Client-Side-Rendering, Server-Side-Rendering 개념 (0) | 2022.10.11 |
[React] Framer Motion(4) AnimatePresence 사용법 및 슬라이드 구현 (0) | 2022.10.02 |
[React] Framer Motion(3) 스크롤(useScroll) 및 로고(SVG파일) 애니메이션 효과 적용 (0) | 2022.10.01 |
[React] Framer Motion(2) 드래그(Drag) 추적 값(useMotionValue) 사용 방법 (1) | 2022.09.30 |