조건부 랜더링을 활용하여 페이지 최초 진입 시, 뜨는 스플래시 화면을 제어 했다.
하지만 화면이 열릴 때와 다르게 닫히는 경우에는 transition
으로 간단하게 페이드 효과를 주고 싶었지만, 적용이 되지 않았다.
내 생각에는 상태값이 false
가 됨과 동시에 컴포넌트는 렌더링이 되지않기 때문에, 효과가 적용이 되지 않는 것이라고 생각된다.
따라서 setTimeOut
함수와 애니메이션을 제어할 새로운 state
를 활용하여 해결했다.
흐름도를 다음과 같이 생각했고, 코드를 작성하였다.
- 컴포넌트(스플래시 스크린)을 2초간 유지
- 2초 후 0.5초 정도의 페이드 아웃 애니메이션을 보여준다.
- 애니메이션을 보여준 후인 0.5초 후 컴포넌트를 렌더링 하지 않는다.
아래는 전체 코드이고, 핵심은 visible 상태와 animation 상태를 두개 나눠서 사용한 점과, useEffect에서 setTimeout을 사용한 점을 보면 될 것 같다.
import { splashScreenState } from "@/common/Recoil/splashScreenState";
import { css, keyframes } from "@emotion/react";
import styled from "@emotion/styled";
import Image from "next/image";
import { useEffect, useState } from "react";
import { useRecoilState } from "recoil";
export default function Splash() {
const [splashFlag, setSplashFlag] = useRecoilState(splashScreenState);
const [animationFlag, setAnimationFlag] = useState(false);
useEffect(() => {
setTimeout(() => {
setAnimationFlag(true);
setTimeout(() => {
setSplashFlag(false);
}, 500);
}, 2000);
}, []);
return (
<>
{splashFlag ? (
<StyledSplash
style={{ backgroundColor: "white" }}
isFadeOut={animationFlag === true}
>
<Image
src={"/images/landing/animation_hi.gif"}
alt="splash"
width={200}
height={200}
/>
</StyledSplash>
) : null}
</>
);
}
const fadeOut = keyframes`
0% {
opacity: 1;
}
100% {
opacity: 0;
}
`;
const StyledSplash = styled.section<{ isFadeOut: boolean }>`
position: absolute;
top: 0px;
left: 0px;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
${(props) =>
props.isFadeOut
? css`
animation: ${fadeOut} 0.5s ease-in-out;
`
: null};
z-index: 999999;
`;