126 lines
4.5 KiB
JavaScript
126 lines
4.5 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import './IntroAnimation.css';
|
|
|
|
export default function IntroAnimation({ onComplete }) {
|
|
const [phase, setPhase] = useState('logo'); // logo -> text -> fade
|
|
const [visible, setVisible] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const timers = [
|
|
setTimeout(() => setPhase('text'), 1500),
|
|
setTimeout(() => setPhase('fade'), 3500),
|
|
setTimeout(() => {
|
|
setVisible(false);
|
|
onComplete?.();
|
|
}, 4500)
|
|
];
|
|
|
|
return () => timers.forEach(clearTimeout);
|
|
}, [onComplete]);
|
|
|
|
if (!visible) return null;
|
|
|
|
return (
|
|
<div className={`intro-animation ${phase}`}>
|
|
{/* Particle field background */}
|
|
<div className="intro-particles">
|
|
{[...Array(50)].map((_, i) => (
|
|
<div
|
|
key={i}
|
|
className="intro-particle"
|
|
style={{
|
|
'--x': `${Math.random() * 100}%`,
|
|
'--y': `${Math.random() * 100}%`,
|
|
'--delay': `${Math.random() * 2}s`,
|
|
'--duration': `${3 + Math.random() * 4}s`,
|
|
'--size': `${1 + Math.random() * 3}px`,
|
|
'--color': ['#ff0000', '#0066ff', '#ffa500'][Math.floor(Math.random() * 3)]
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* Animated logo */}
|
|
<div className="intro-logo-container">
|
|
<svg className="intro-logo" viewBox="0 0 200 200" width="200" height="200">
|
|
<defs>
|
|
<linearGradient id="intro-trinity" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stopColor="#ff0000"/>
|
|
<stop offset="50%" stopColor="#0066ff"/>
|
|
<stop offset="100%" stopColor="#ffa500"/>
|
|
</linearGradient>
|
|
<filter id="intro-glow">
|
|
<feGaussianBlur stdDeviation="3" result="blur"/>
|
|
<feMerge>
|
|
<feMergeNode in="blur"/>
|
|
<feMergeNode in="SourceGraphic"/>
|
|
</feMerge>
|
|
</filter>
|
|
</defs>
|
|
|
|
{/* Outer diamond */}
|
|
<path
|
|
className="intro-diamond-outer"
|
|
d="M100 10 L190 100 L100 190 L10 100 Z"
|
|
fill="none"
|
|
stroke="url(#intro-trinity)"
|
|
strokeWidth="2"
|
|
filter="url(#intro-glow)"
|
|
/>
|
|
|
|
{/* Inner diamond */}
|
|
<path
|
|
className="intro-diamond-inner"
|
|
d="M100 40 L160 100 L100 160 L40 100 Z"
|
|
fill="url(#intro-trinity)"
|
|
opacity="0.2"
|
|
/>
|
|
|
|
{/* Center pulse */}
|
|
<circle
|
|
className="intro-core"
|
|
cx="100"
|
|
cy="100"
|
|
r="15"
|
|
fill="url(#intro-trinity)"
|
|
/>
|
|
|
|
{/* Orbiting dots */}
|
|
<circle className="intro-orbit intro-orbit-1" r="4" fill="#ff0000"/>
|
|
<circle className="intro-orbit intro-orbit-2" r="4" fill="#0066ff"/>
|
|
<circle className="intro-orbit intro-orbit-3" r="4" fill="#ffa500"/>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* Text reveal */}
|
|
<div className="intro-text-container">
|
|
<h1 className="intro-title">
|
|
<span className="intro-letter" style={{ '--i': 0 }}>A</span>
|
|
<span className="intro-letter" style={{ '--i': 1 }}>e</span>
|
|
<span className="intro-letter" style={{ '--i': 2 }}>T</span>
|
|
<span className="intro-letter" style={{ '--i': 3 }}>h</span>
|
|
<span className="intro-letter" style={{ '--i': 4 }}>e</span>
|
|
<span className="intro-letter" style={{ '--i': 5 }}>x</span>
|
|
<span className="intro-space"> </span>
|
|
<span className="intro-letter" style={{ '--i': 6 }}>C</span>
|
|
<span className="intro-letter" style={{ '--i': 7 }}>o</span>
|
|
<span className="intro-letter" style={{ '--i': 8 }}>n</span>
|
|
<span className="intro-letter" style={{ '--i': 9 }}>n</span>
|
|
<span className="intro-letter" style={{ '--i': 10 }}>e</span>
|
|
<span className="intro-letter" style={{ '--i': 11 }}>c</span>
|
|
<span className="intro-letter" style={{ '--i': 12 }}>t</span>
|
|
</h1>
|
|
<p className="intro-tagline">The Trinity of Communication</p>
|
|
</div>
|
|
|
|
{/* Scan line effect */}
|
|
<div className="intro-scanline" />
|
|
|
|
{/* Corner accents */}
|
|
<div className="intro-corner intro-corner-tl" />
|
|
<div className="intro-corner intro-corner-tr" />
|
|
<div className="intro-corner intro-corner-bl" />
|
|
<div className="intro-corner intro-corner-br" />
|
|
</div>
|
|
);
|
|
}
|