Neue services
This commit is contained in:
111
components/LoadingScreen.tsx
Normal file
111
components/LoadingScreen.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import gsap from 'gsap';
|
||||
|
||||
interface LoadingScreenProps {
|
||||
onComplete: () => void;
|
||||
}
|
||||
|
||||
const LoadingScreen: React.FC<LoadingScreenProps> = ({ onComplete }) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const textRef = useRef<HTMLDivElement>(null);
|
||||
const progressRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Hide scrolling on the body while loading
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
const tl = gsap.timeline({
|
||||
onComplete: () => {
|
||||
document.body.style.overflow = '';
|
||||
onComplete();
|
||||
},
|
||||
});
|
||||
|
||||
const chars = textRef.current?.querySelectorAll('.char');
|
||||
|
||||
// 1. Initial state: progress bar width 0
|
||||
gsap.set(progressRef.current, { scaleX: 0, transformOrigin: 'left center' });
|
||||
if (chars) {
|
||||
gsap.set(chars, { yPercent: 100, opacity: 0 });
|
||||
}
|
||||
|
||||
// 2. Animate the progress bar and reveal text simultaneously
|
||||
tl.to(progressRef.current, {
|
||||
scaleX: 1,
|
||||
duration: 1.5,
|
||||
ease: 'power3.inOut',
|
||||
})
|
||||
.to(
|
||||
chars || [],
|
||||
{
|
||||
yPercent: 0,
|
||||
opacity: 1,
|
||||
duration: 0.8,
|
||||
stagger: 0.05,
|
||||
ease: 'power4.out',
|
||||
},
|
||||
'<0.5' // Start this animation 0.5s into the progress bar loading
|
||||
)
|
||||
// 3. Keep it visible briefly
|
||||
.to({}, { duration: 0.3 })
|
||||
// 4. Slide out the individual characters upwards
|
||||
.to(
|
||||
chars || [],
|
||||
{
|
||||
yPercent: -100,
|
||||
opacity: 0,
|
||||
duration: 0.5,
|
||||
stagger: 0.02,
|
||||
ease: 'power3.in',
|
||||
}
|
||||
)
|
||||
// 5. Fade out progress line
|
||||
.to(progressRef.current, { opacity: 0, duration: 0.3 }, '<')
|
||||
// 6. Slide the whole curtain up to reveal the homepage
|
||||
.to(containerRef.current, {
|
||||
yPercent: -100,
|
||||
duration: 1,
|
||||
ease: 'expo.inOut',
|
||||
});
|
||||
|
||||
return () => {
|
||||
tl.kill();
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
}, [onComplete]);
|
||||
|
||||
const text = 'BAY AREA IT';
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="fixed inset-0 z-[9999] flex flex-col items-center justify-center bg-surface-dark dark:bg-background-dark text-primary"
|
||||
>
|
||||
<div className="relative overflow-hidden mb-8">
|
||||
<h1
|
||||
ref={textRef}
|
||||
className="font-display text-4xl md:text-6xl font-bold tracking-widest flex overflow-hidden"
|
||||
>
|
||||
{text.split('').map((char, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className={`char inline-block opacity-0 ${char === ' ' ? 'w-4' : ''}`}
|
||||
>
|
||||
{char}
|
||||
</span>
|
||||
))}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Sleek Minimalist Loading Line */}
|
||||
<div className="w-48 md:w-64 h-[2px] bg-white/10 rounded-full overflow-hidden">
|
||||
<div
|
||||
ref={progressRef}
|
||||
className="h-full w-full bg-primary origin-left scale-x-0"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingScreen;
|
||||
Reference in New Issue
Block a user