조건부 렌더링 시, 컴포넌트가 닫힐 때 애니메이션 효과

준영·2023년 8월 22일
0

코드 지갑..

목록 보기
16/20
post-thumbnail

조건부 랜더링을 활용하여 페이지 최초 진입 시, 뜨는 스플래시 화면을 제어 했다.
하지만 화면이 열릴 때와 다르게 닫히는 경우에는 transition 으로 간단하게 페이드 효과를 주고 싶었지만, 적용이 되지 않았다.

내 생각에는 상태값이 false가 됨과 동시에 컴포넌트는 렌더링이 되지않기 때문에, 효과가 적용이 되지 않는 것이라고 생각된다.

따라서 setTimeOut함수와 애니메이션을 제어할 새로운 state를 활용하여 해결했다.

흐름도를 다음과 같이 생각했고, 코드를 작성하였다.

  1. 컴포넌트(스플래시 스크린)을 2초간 유지
  2. 2초 후 0.5초 정도의 페이드 아웃 애니메이션을 보여준다.
  3. 애니메이션을 보여준 후인 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;
`;
profile
개인 이력, 포폴 관리 및 기술 블로그 사이트 👉 https://aimzero-web.vercel.app/

0개의 댓글