팀프로젝트를 진행하면서 적용하면 좋을 적절한 애니메이션을 고민하던 중,
아주 유용하게 사용할 수 있을 것 같은 라이브러리를 발견했다.
React-Spring의 가장 큰 장점은 애니메이션이 실행될때 re-render가 되지 않는다는 점이다.
일반적으로 react에서 useState 값을 사용하여 클릭 상태 변화에 따라 애니메이션을 다시 그려야하므로 리렌더 될 수 밖에 없다.
하지만 useSpring을 사용하면 해당 과정 없이 애니메이션을 동작시킬수 있다고 한다.
눈에 보이는 효과는 아직 없겠지만, 관리해야 할 useState가 많거나, 애니메이션을 많이 사용하게되면 매우 유용할 것 같다
import * as S from "./index.styled";
import { animated, useSpring } from "@react-spring/web";
export default function Page1() {
const springs = useSpring({
from: { x: 0 },
to: { x: 100 },
})
return (
<S.Container>
<S.Wrapper>
<animated.div
style={{
width: 80,
height: 80,
background: "#ff6d6d",
borderRadius: 8,
...springs,
}}
/>
</S.Wrapper>
</S.Container>
);
}
일반적인 태그가 아니라 <animated.div/> 태그 의 style 속성으로 스타일할 수 있고, 애니메이션을 주기 위해서 useSpring을 사용해야한다. 이렇게 사용하면 첫 페이지 렌더링시 x가 100만큼 1번 이동한다. ( 배경 및 배치는 emotion/styled 사용 중 )
평소 사용하는 hooks 처럼 useSpring안에 원하는 애니메이션을 넣어주고 태그안에 ...spring을 바인딩시켜주면 끝이다!
클릭시 원하는 애니메이션을 작동시켜주는 것은 useSpring안에 api 라는 메서드를 추가하고, 함수로 변경하면된다.
const [springs, api] = useSpring(() => ({
from: { x: 0, y: 0 },
}));
const handleClick = () => {
api.start({
from: {
x: 0,
y: 0,
},
to: {
x: 100,
y: 100,
},
});
};
handleClick은 animated.div 태그 onClick에 적용
그럼 React-Spring을 이용해서 아래 애니메이션을 만들어보자
CSS와 React만 사용해도 만들 수 있을 것 같지만 이번에는 React-Spring을 사용하면 좋을 것 같았다.
기본원리는 두 이미지가 동일한 위치와 사이즈로 있으며 투명도가 서로 0 -> 1, 1 -> 0 으로 변경되는고 x 축으로 180도씩 돌아가게 하는 것이다.
내가 사용하는 css 라이브러리인 emotion/styled와 예시 코드로 제공되는 css 방법이 다르기때문에 약간의 변화가 필요했다...
useSpring 에서 제공하는 태그를 사용한 후 style을 적용해야 하므로 css에서 Wrapper 의 div, Wrapper의 span으로 구분하였다.
import * as S from "./index.styled";
import { animated, useSpring } from "@react-spring/web";
import { useState } from "react";
export default function Page1() {
const [rotate, setRotate] = useState(false);
const { transform, opacity } = useSpring({
opacity: rotate ? 1 : 0,
transform: `perspective(500px) rotateX(${rotate ? 180 : 0}deg)`,
});
const onClickRotate = () => {
setRotate((prev) => !prev);
};
return (
<S.Container>
<S.Wrapper onClick={onClickRotate}>
<animated.div
style={{ opacity: opacity.to((o) => 1 - o), transform }}
/>
<animated.span style={{ opacity, transform, rotateX: "180deg" }} />
</S.Wrapper>
</S.Container>
);
}
import styled from "@emotion/styled";
import * as GS from "../../../../theme/global";
export const Container = styled.div`
width: 100%;
height: 100vh;
background-color: ${GS.base.primary};
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
`;
export const Wrapper = styled.div`
width: 82%;
height: 80%;
position: relative;
div {
display: flex;
width: 500px;
height: 300px;
background-color: black;
position: absolute;
opacity: 1;
cursor: pointer;
::before {
content: "kk-jae 앞면입니다.";
color: white;
}
}
span {
display: flex;
width: 500px;
height: 300px;
background-color: pink;
position: absolute;
opacity: 0;
cursor: pointer;
::before {
content: "kk-jae 뒷면입니다";
}
}
`;
애니메이션을 다채롭게 적용하기 위해서는 css 셀렉터도 다시 한번 학습할 필요가 있을 것 같다.
React-Spring https://www.react-spring.dev/
React Spring
Bring your components to life with simple spring animation primitives for React
www.react-spring.dev
'리액트' 카테고리의 다른 글
구조분해 할당(비구조화 할당) (0) | 2023.02.21 |
---|---|
Pagination과 Infinite Scroll 설계 (0) | 2023.02.05 |
useRef 어떻게 사용할까? (0) | 2023.02.05 |
클래스형 컴포넌트와 함수형 컴포넌트의 state lifecycle 기능 (0) | 2023.02.05 |
클래스형(Class) 컴포넌트와 함수형(Functional) 컴포넌트 (0) | 2023.02.05 |