보완 및 추가된 내용:
- 비디오 로딩이 끝날 때까지 로딩 스피너 표시 (UX 개선)
- 비디오 파일이 없거나 로드 실패 시 폴백 이미지 표시 (에러 처리)
- 스타일 개선 (조금 더 깔끔한 디자인을 위해 세부적 스타일링 추가)
- 타입 안정성 확보 (PropTypes 추가)
- 유지보수 및 가독성 향상 (리팩토링)
src/components/VideoBackground.jsx
import React, { useState } from 'react';
import PropTypes from 'prop-types';
const VideoBackground = ({ videoSrc, fallbackImage, overlayText }) => {
const [isVideoLoaded, setIsVideoLoaded] = useState(false);
const [isError, setIsError] = useState(false);
return (
<div className="relative w-full h-screen overflow-hidden">
{!isVideoLoaded && !isError && (
<div className="absolute inset-0 bg-black flex items-center justify-center z-20">
<div className="loader animate-spin rounded-full h-12 w-12 border-t-4 border-white"></div>
</div>
)}
{isError ? (
<img
src={fallbackImage}
alt="Background fallback"
className="absolute top-0 left-0 w-full h-full object-cover z-0"
/>
) : (
<video
autoPlay
loop
muted
playsInline
className={`absolute top-0 left-0 w-full h-full object-cover z-0 transition-opacity duration-1000 ${isVideoLoaded ? 'opacity-100' : 'opacity-0'}`}
onLoadedData={() => setIsVideoLoaded(true)}
onError={() => setIsError(true)}
>
<source src={videoSrc} type="video/mp4" />
브라우저가 비디오를 지원하지 않습니다.
</video>
)}
<div className="absolute inset-0 z-10 flex items-center justify-center bg-black bg-opacity-50 text-white">
<h1 className="text-4xl md:text-5xl font-bold shadow-lg">
{overlayText}
</h1>
</div>
</div>
);
};
VideoBackground.propTypes = {
videoSrc: PropTypes.string.isRequired,
fallbackImage: PropTypes.string.isRequired,
overlayText: PropTypes.string,
};
VideoBackground.defaultProps = {
overlayText: '안녕하세요 반갑습니다!',
};
export default VideoBackground;
사용 예시 (src/App.jsx에 적용하기)
import React from 'react';
import VideoBackground from './components/VideoBackground';
import { motion, useScroll } from 'framer-motion';
import Header from './components/Header';
import Hero from './components/Hero';
import About from './components/About';
import ServicesSection from './components/ServicesSection';
import StatsSection from './components/StatsSection';
import ProjectGallery from './components/ProjectGallery';
import BlogSlider from './components/BlogSlider';
import SimpleCounter from './components/SimpleCounter';
import SimpleTodo from './components/SimpleTodo';
import SimpleCalculator from './components/SimpleCalculator';
import ThreeDPortfolio from './components/ThreeDPortfolio';
import AvatarPortfolio from './components/AvatarPortfolio';
import ParticlePortfolio from './components/ParticlePortfolio';
import Contact from './components/Contact';
function App() {
const { scrollYProgress } = useScroll();
return (
<>
<motion.div
id="scroll-indicator"
style={{
scaleX: scrollYProgress,
position: 'fixed',
top: 0,
left: 0,
right: 0,
height: '10px',
backgroundColor: '#ff0088',
zIndex: 9999,
transformOrigin: '0% 50%',
}}
/>
<div style={{ minHeight: '200vh' }}>
<VideoBackground
videoSrc="/videos/intro.mp4"
fallbackImage="/images/fallback.jpg"
overlayText="환영합니다! 멋진 페이지에 오신 걸 환영해요!"
/>
<Header />
<Hero />
<About />
<ServicesSection />
<StatsSection />
<ProjectGallery />
<BlogSlider />
<SimpleCounter />
<SimpleTodo />
<SimpleCalculator />
<ThreeDPortfolio />
<AvatarPortfolio />
<ParticlePortfolio />
<Contact />
</div>
</>
);
}
export default App;
Tailwind CSS 스타일링 추가하기 (tailwind.config.js에 다음을 추가)
// tailwind.config.js
module.exports = {
// 생략
theme: {
extend: {
animation: {
spin: 'spin 1s linear infinite',
},
keyframes: {
spin: {
to: { transform: 'rotate(360deg)' },
},
},
},
},
};
추가 설명:
- 로딩 스피너: 동영상이 로딩되는 동안 사용자가 지루하지 않도록 UX 개선.
- 폴백 이미지: 영상이 로드되지 않거나 파일이 존재하지 않을 경우를 대비해 이미지 제공으로 오류 화면 방지.
- Props 활용: VideoBackground 컴포넌트를 재사용 가능하게 만들어 다양한 영상 및 텍스트 지원 가능.
'React' 카테고리의 다른 글
질문답변, React + Typescript 사용중 발생한 오류 (0) | 2024.05.04 |
---|---|
질문답변 2024-01-27 React Router (2) | 2024.01.27 |
왜? 무한루프가 도는지? (0) | 2023.11.12 |
프론트 개발 실무에서 로그인 회원가입 만들때 authGuard를 사용하시나요? (0) | 2023.09.16 |
<table> 태그에서, 테이블에서 원하는 테두리 반경 효과 (2) | 2023.08.29 |