드롭다운 메뉴에서 아이콘을 클릭하면 제자리에서 부드럽게 회전하는 애니메이션을 구현해보려고 한다.
완성된 모습은 아래와 같다.
여러가지 방법이 있겠지만 나는 CSS 구현시 Styled-components를 이용하고 있으므로 keyframes를 import해서 사용했다.
import styled, { keyframes } from "styled-components";
클릭하면 0도에서 180도로, 다시 클릭하면 180도에서 0도로 돌아와야 한다.
즉 애니메이션 두 개를 만든다.
(완성하고 나서 animation-direction 속성으로 reverse를 주면 반대 방향으로 변경할 수 있다는 걸 알게 됐다. 다음 번엔 이걸로 해봐야겠음)
const AniUp = keyframes`
0% {
transform:rotate(0deg);
}
100%{
transform:rotate(180deg);
}
`;
const AniDown = keyframes`
0% {
transform:rotate(180deg);
}
100%{
transform:rotate(0deg);
}
`;
(0%는 시작 지점, 100%는 끝 지점을 뜻함. 중간에 50%같은거 넣어도 됨)
그 다음 span 태그를 만들어서 애니메이션을 넣어 주었다.
(여기서는 span을 썼지만 div든 p든 아무거나 써도 상관없음)
const Animation1 = styled.span`
animation: ${AniDown} 0.35s linear forwards;
`;
const Animation2 = styled.span`
animation: ${AniUp} 0.35s linear forwards;
`;
이제 애니메이션을 만들었으니 아이콘이 위치한 헤더로 간다.
H O W E V E R ..........
지난번 드롭다운 메뉴를 만들 때 useState를 이용해서 true, false로 메뉴가 보일지 안보일지 결정했었다. 그런데 애니메이션을 넣으니 클릭을 하지 않고 새로고침만 했을 때도 애니메이션이 실행되는 문제가 발생했다. (=초기값이 false이기 때문에 드롭다운 아이콘이 위로 돌아가는 애니메이션 실행됨)
이 문제를 해결하기 위해 true, false 외에 null 값을 초기값으로 두었다.
const [view, setView] = useState(null);
...중략...
<HeaderUl
onClick={() => {
setView((prev) => {
return !prev ? true : false;
});
}}
>
반가워요, nickName 님!{" "}
{view === null && (
<div>
<KeyboardArrowDownIcon viewBox="0 -7 24 24" />
</div>
)}
{view && (
<>
<Animation1>
<div>
<KeyboardArrowUpIcon viewBox="0 -5 24 24" />
</div>
</Animation1>
<Dropdown />
</>
)}
{view === false && (
<Animation2>
<div>
<KeyboardArrowUpIcon viewBox="0 -5 24 24" />
</div>
</Animation2>
)}
</HeaderUl>
falsy 값: false, null, undefined, 0, ""(빈 문자열), NaN
view가 null일 경우 정지해 있는 KeyboardArrowDownIcon을 보여준다.
view가 true일 경우 Animation1을 실행하고 Dropdown 컴포넌트를 보여준다.
view가 false일 경우 Animation2를 실행한다.
viewBox="0 -7 24 24" 는 아이콘(svg) 위치와 크기 설정값.
아이콘을 div로 감싸준 이유는 중앙을 잡아줘야 제자리에서 돌기 때문