layout이라는 prop을 element에 주면 그 element의 layout이 바뀔 때, animation이 발생한다.
layoutId를 사용하여 두 컴포넌트가 같은 컴포넌트로 인식되도록 할 수 있다.
const Wrapper = styled(motion.div)`
height: 100vh;
width: 100vw;
display: flex;
/* justify-content: center; */
justify-content: space-around;
align-items: center;
flex-direction: column;
`;
const Box = styled(motion.div)`
width: 400px;
height: 400px;
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;
const Circle = styled(motion.div)`
background-color: #a3cca2;
width: 100px;
height: 100px;
border-radius: 50%;
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>
{!clicked ? (
<Circle layoutId="circle" style={{ borderRadius: "50%" }} />
) : null}
</Box>
<Box>
{clicked ? (
<Circle layoutId="circle" style={{ borderRadius: "0%" }} />
) : null}
</Box>
</Wrapper>
);
}
export default App;
const Wrapper = styled.div`
height: 100vh;
width: 100vw;
display: flex;
/* justify-content: center; */
justify-content: space-around;
align-items: center;
`;
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 Grid = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
width: 50vw;
div:first-child,
div:last-child {
grid-column: span 2;
}
`;
const Overlay = styled(motion.div)`
width: 100%;
height: 100%;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
`;
const overlay = {
hidden: { backgroundColor: "rgba(0, 0, 0, 0)" },
visible: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
exit: { backgroundColor: "rgba(0, 0, 0, 0)" },
};
function App() {
const [id, setId] = useState<null | string>(null);
return (
<Wrapper>
<Grid>
{["1", "2", "3", "4"].map((n) => (
<Box onClick={() => setId(n)} key={n} layoutId={n} />
))}
</Grid>
<AnimatePresence>
{id ? (
<Overlay
onClick={() => setId(null)}
variants={overlay}
initial="hidden"
animate="visible"
exit="exit"
>
<Box layoutId={id} style={{ width: 400, height: 200 }} />
</Overlay>
) : null}
</AnimatePresence>
</Wrapper>
);
}
export default App;