페이드인 오프닝 화면 만들기
ㆍProject Diary/React + Firebase (Snack ShoppingMall)
웹사이트에 처음 접속할 때 부드럽게 페이드인되는 오프닝 화면 구현 방법 기록
오프닝 화면은 배경 이미지와 애니메이션 요소들로 구성되며, 스크롤에 반응하여 동적으로 변하는 기능을 구현할 것입니다.
사실, 이 작업은 꽤 노가다(수작업)라서 코드는 장황해질 수밖에 없습니다. 그래도 최종 결과물은 꽤 멋질 거예요!...??
주요 기술
- CSS 애니메이션
- React와 styled-components
1. 페이드인 애니메이션 적용
import React, { useEffect, useState } from 'react';
import styled, { keyframes } from 'styled-components';
const fadeIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`;
const OpeningBlock = styled.div`
height: 100vh;
width: 100vw;
background: #fff;
display: flex;
justify-content: center;
align-items: center;
animation: ${fadeIn} 2s ease-in-out;
`;
const OpeningText = styled.h1`
font-size: 3rem;
color: #333;
`;
const Opening = () => {
const [show, setShow] = useState(false);
useEffect(() => {
setShow(true);
}, []);
return (
<OpeningBlock>
{show && <OpeningText>Welcome to Our Website</OpeningText>}
</OpeningBlock>
);
};
export default Opening;
2. 이미지 레이어 설정
오프닝 화면에 사용할 이미지를 설정합니다. 각 이미지의 경로를 import하고, styled-components를 사용하여 스타일을 정의합니다. 이 부분이 꽤 장황한데, 이미지가 많고 각각의 위치와 애니메이션을 설정해야 하기 때문입니다.
import React from "react";
import styled from "styled-components";
import backImg from "../../assets/image/fadein/1_sky_pc-b0963240.jpg";
import ground from "../../assets/image/fadein/1_ground1_pc-979ead8b.png";
import ground2 from "../../assets/image/fadein/1_ground2_pc-648eb135.png";
import ground3 from "../../assets/image/fadein/1_ground3_pc-907636de.png";
import leftBush from "../../assets/image/fadein/1_l1_pc-4f293b0e.png";
import leftGrass from "../../assets/image/fadein/1_l3_pc-b5ade620.png";
import leftTree from "../../assets/image/fadein/1_l4_pc-357ac1e3.png";
import rightBush from "../../assets/image/fadein/1_r1a_pc-66a6a5f0.png";
import rightGrass from "../../assets/image/fadein/1_r3_pc-aff410d0.png";
import rightTree from "../../assets/image/fadein/1_r4_pc-e78cd55d.png";
import people from "../../assets/image/fadein/1_people1_pc-86bbbf37.png";
import logo from "../../assets/image/logo_img1b.svg";
const OpeningBlock = styled.div`
background: url(${backImg});
background-size: cover;
background-position: center;
height: 100vh;
width: 100vw;
max-width: 100%;
top: 0;
left: 0;
position: fixed;
overflow: hidden;
z-index: 1000;
img {
position: absolute;
transition: all 0.5s ease;
background: transparent;
}
`;
const LogoWrapper = styled.div`
z-index: 9000;
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
`;
const Text = styled.svg`
font-size: 50px;
font-weight: 600;
fill: #5a4620;
stroke: #5a4620;
stroke-width: 0.75px;
stroke-linecap: round;
stroke-linejoin: round;
`;
const LogoImage = styled.img`
animation: ${fadeIn} 3s ease-in-out forwards;
`;
const Opening = ({ scrollPosition }) => {
return (
<OpeningBlock scrollPosition={scrollPosition}>
<div className="overlay">
<img src={ground3} alt="" />
<img src={ground2} alt="" />
<img src={ground} alt="" />
<img src={people} alt="" />
<img src={leftTree} alt="" />
<img src={leftBush} alt="" />
<img src={leftGrass} alt="" />
<img src={rightTree} alt="" />
<img src={rightBush} alt="" />
<img src={rightGrass} alt="" />
<LogoWrapper scrollPosition={scrollPosition}>
<LogoImage src={logo} alt="Logo" />
<Text width="400" height="100" viewBox="0 0 400 100">
<text x="50%" y="50%" dy=".3em" textAnchor="middle">
쿠와자와 과자점
</text>
</Text>
</LogoWrapper>
</div>
</OpeningBlock>
);
};
export default Opening;
스크롤 이벤트를 처리하기 위해 상위 컴포넌트에서 상태와 이벤트 핸들러를 설정합니다.
src/App.js
import React, { useState, useEffect } from 'react';
import Opening from './components/opening/Opening';
const App = () => {
const [scrollPosition, setScrollPosition] = useState(0);
const handleScroll = () => {
setScrollPosition(window.scrollY);
};
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<div>
<Opening scrollPosition={scrollPosition} />
<div style={{ height: '200vh' }}>
Scroll down to see the effect
</div>
</div>
);
};
export default App;
이렇게 하면 페이드인 오프닝 화면을 만들었습니다. 사실, 이 작업은 이미지가 많고 각 요소의 위치와 애니메이션을 세밀하게 조정해야 하므로 꽤 장황한 코드가 되더라구요. 하지만 최종 결과물은 웹사이트의 첫 인상을 크게 향상시킬 수 있습니다.