โ
fill="currentColor"
์ผ ๋ path๋ svg์ color๋ฅผ ์ฐ๊ฒ ๋๋ค.
โ
pathLength
๋ ํ์ฌ ์ฐ๋ฆฌ ์์น๊น์ง์ path์ ๊ธธ์ด
๋ง์ง๋ง์ผ๋ก ํน์ property์ animation duration์ ๋จ๋
์ผ๋ก ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
pathLength๊ฐ 0์์ 1๋ก ๊ฐ๋๊ฒ, fill์ opacity๊ฐ 0์์ 1๋ก ๊ฐ๋ ๊ฒ ๋ชจ๋ 5์ด๊ฐ ๊ฑธ๋ฆฐ๋ค.
const svg = {
start: { pathLength: 0, fill: "rgba(255,255,255,0)" },
end: {
pathLength: 1,
fill: "rgba(255,255,255,1)",
transition: { duration: 5 },
},
};
์ ์ฝ๋์ ๊ฐ์ด transition: {duration:5} ๋ก ์์ฑํ๊ธฐ ๋๋ฌธ์ ๋๊ฐ์ด 5์ด๊ฐ ๊ฑธ๋ฆฌ๊ฒ ๋๋๊ฒ์ธ๋ฐ, ์ด๋ฅผ ์์ ํด๋ณด์.
<motion.path transition={{
default: { duration: 5 },
fill: { duration: 2, delay: 5 }, }} />
์ง์ ์ ์ผ๋ก ์ด๋ค property๋ฅผ ์ด๋ป๊ฒ, ์ผ๋ง๋ animation ํ ์ง ํน์ ํ ์ ์๋ ๊ฒ์ด๋ค. default๋ ๋ชจ๋ propery์ ์ ์ฉ๋๋ ๊ฐ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค๐คฃ
AnimatePresence
๋ React js App์์ ์ฌ๋ผ์ง๋ component๋ฅผ animateํ๋ component ์ด๋ค.
AnimatePresence๋ visible ์ํ์ฌ์ผ ํ๊ณ , ๋ด๋ถ์๋ condition(์กฐ๊ฑด๋ฌธ)์ด ์์ด์ผํ๋ค๋ ๊ฒ์ด๋ค.
๋ํ๋๋ Box์ ์ฌ๋ผ์ง๋ Box๋ฅผ ํน์ ํด์ ์ฌ๋ผ์ด๋๋ฅผ ๋ง๋ค์ด ๋ณด์.
๊ฐ๋จํ๊ฒ prev์ next ๋ฒํผ์ ๋ง๋ค์๋๋ฐ, prev๋ฅผ ๋๋ฅด๋ฉด ์ ์๋ํ๊ธด ํ์ง๋ง next๋ฅผ ๋๋ ์ ๋๋ ๊ฐ์ ๋ฐฉํฅ์์ ๋ํ๋๋ ๋ฌธ์ ์ ์ด ์๋๋ฐ ๋ค์ ์ฑํฐ์์ ๋ฐฐ์๋ณด์.
โ ๋ฐฐ์ด์ ์์ ๊ณ ๋ ๊น๋ํ๊ฒ ์ฝ๋๋ฅผ ์์ฑํด๋ณด์. element์ key๋ฅผ ๋ฐ๊ฟ์ฃผ๋ ๊ฒ ๋ง์ผ๋ก๋ React js๋ element๊ฐ ์ฌ๋ผ์ก๋ค๊ณ ์๊ฐํด์ ewit animation์ ์คํํ ๊ฒ์ด๋ค.
โ
prev ๋ฒํผ์ ๋๋ ์ ๋ ๋ฐ๋๋ฐฉํฅ์ผ๋ก ๊ฐ์์๋๋ก ํด๋ณผ๊ฑด๋ฐ, custom
์ด๋ property์ ๋ํด์ ์์๋ณด์.
custom
์ variants์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ ์๊ฒ ํด์ฃผ๋ property์ด๋ค.
โ
next๋ฅผ ๋๋ฅด๋ฉด 1๋ฒ Box์ exit animation์ด ์คํ๋๋ ๋์ 2๋ฒ Box์ entry๊ฐ ๊ฑฐ์ ๋์์ ์คํ๋๋ค. ํ๋๊ฐ ์คํ๋ ๋ค์ ๋ค์ ๊ฒ์ด ์คํ๋๋๊ฒ์ด ์๋๋ผ animation์ด ๊ฑฐ์ ํจ๊ป ์์ํ๋ค๋ ๊ฒ.
exitBeforeEnter
์ ์ด์ฉํ์ฌ ๋ณ๊ฒฝํด์ค ์ ์๋ค. exit์ ์คํ์ํค๊ณ exit์ด ๋๋๋ฉด ๋ค์ element๋ฅผ ์ฌ ์ ์๋๋ก ํด์ค๋ค. ๋ฐ๋ผ์ 1๋ฒ Box์ exit์ด ์์ ํ๊ฒ ์คํ๋์ ๋๋ง 2๋ฒ Box๊ฐ ์ค๊ฒ ๋๋ค!
โ exitBeforeEnter๋ ๋ ์ด์ ์ง์ํ์ง ์์ผ๋ฏ๋ก mode="wait"
๋ฅผ ์์ฑํด์ ๊ตฌํํ๋ฉด ๋๋ค.
layout
์ด๋ผ๋ prop์ ๋ฐฐ์๋ณด์. ์ด prop์ element์๊ฒ ์ฃผ๋ฉด ๊ทธ element์ layout์ด ๋ฐ๋ ๋ ์์์ animate๊ฐ ๋๋ค. css์ ๋ณํ๊ฐ ์๋์ผ๋ก animate ๋๋ค๋ ๊ฒ!
์ํ๋ ์ปดํฌ๋ํธ์ layout
๋ง ์์ฑํด์ฃผ๋ฉด ์ ๋ง ๊ฐ๋จํ๊ฒ ๊ตฌํ ๊ฐ๋ฅ๐คฃ
const Box = styled(motion.div)`
width: 400px;
height: 400px;
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
display: flex;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;
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",
}}
>
<Circle layout />
</Box>
</Wrapper>
);
}
๋๋ฒ์งธ๋ก shared layout animation
์ ๋ฐฐ์๋ณด์.
๋๊ฐ ๊ฐ๊ฐ์ ์๋ก ๋ค๋ฅธ component์ธ Circle์ด ๊ฐ์ component๋ผ๊ณ Framer์๊ฒ ํจ๊ป ์ฐ๊ฒฐ๋๋ค๊ณ ๋งํด์ฃผ๋ฉด ๋๋๋ฐ, layoutId
๋ฅผ ํ์ฉํ๋ฉด ์ฝ๊ฒ ๊ตฌํ์ด ๊ฐ๋ฅํ๋ค๐คฃ
8.14์ ์ด์ด layoutId
๋ฅผ ์ด์ฉํ์ฌ ๋ค๋ฅธ component์ด์ง๋ง ํจ๊ป ๋ฌถ๊ณ ๊ฐ๊ฐ ๋ค๋ฅธ state๋ฅผ animate ํด๋ณด์.
๋ค๋ฅธ Box๋ ํด๋ฆญํ ์ ์๊ฒ ํ๊ณ , ํด๋ฆญํ ๊ฐ Box๋ฅผ ์ค์์ผ๋ก ๊ฐ๊ฒ ํด๋ณด์. (์ด๋ element๋ฅผ ํด๋ฆญํด๋ ์๋๋๋๋ก)