Files
personal_website/src/components/GlitchCrash.tsx
T

168 lines
5.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import { motion } from 'framer-motion';
interface GlitchCrashProps {
onComplete?: () => void;
}
const GlitchCrash = ({ onComplete }: GlitchCrashProps) => {
const [phase, setPhase] = useState(0);
const [glitchText, setGlitchText] = useState('');
const errorMessages = [
'BUFFER OVERFLOW DETECTED',
'STACK SMASHING DETECTED',
'SEGMENTATION FAULT',
'MEMORY CORRUPTION',
'KERNEL PANIC',
'SYSTEM HALTED',
'0xDEADBEEF',
'FATAL ERROR',
'CORE DUMPED',
];
useEffect(() => {
const interval = setInterval(() => {
const chars = '!@#$%^&*()_+-=[]{}|;:,.<>?/~`░▒▓█▀▄▌▐■□▢▣▤▥▦▧▨▩';
let text = '';
for (let i = 0; i < 100; i++) {
text += chars[Math.floor(Math.random() * chars.length)];
if (i % 20 === 19) text += '\n';
}
setGlitchText(text);
}, 50);
const phaseTimer = setInterval(() => {
setPhase(p => p + 1);
}, 800);
const endTimer = setTimeout(() => {
onComplete?.();
}, 8000);
return () => {
clearInterval(interval);
clearInterval(phaseTimer);
clearTimeout(endTimer);
};
}, [onComplete]);
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="fixed inset-0 z-[9999] bg-background overflow-hidden"
style={{
animation: 'glitchShake 0.1s infinite',
}}
>
<style>{`
@keyframes glitchShake {
0% { transform: translate(0, 0) skew(0deg); }
20% { transform: translate(-5px, 3px) skew(1deg); }
40% { transform: translate(5px, -2px) skew(-1deg); }
60% { transform: translate(-3px, 5px) skew(0.5deg); }
80% { transform: translate(3px, -5px) skew(-0.5deg); }
100% { transform: translate(0, 0) skew(0deg); }
}
@keyframes glitchColor {
0% { filter: hue-rotate(0deg) saturate(2) brightness(1.5); }
25% { filter: hue-rotate(90deg) saturate(3) brightness(2); }
50% { filter: hue-rotate(180deg) saturate(2) brightness(1); }
75% { filter: hue-rotate(270deg) saturate(4) brightness(2.5); }
100% { filter: hue-rotate(360deg) saturate(2) brightness(1.5); }
}
@keyframes scanline {
0% { transform: translateY(-100%); }
100% { transform: translateY(100vh); }
}
`}</style>
{/* Glitch color overlay */}
<div
className="absolute inset-0 mix-blend-overlay"
style={{ animation: 'glitchColor 0.3s infinite' }}
/>
{/* Scanlines */}
<div
className="absolute inset-0 pointer-events-none"
style={{
background: 'repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.3) 2px, rgba(0,0,0,0.3) 4px)',
animation: 'scanline 0.5s linear infinite',
}}
/>
{/* Random noise */}
<pre className="absolute inset-0 text-primary/30 text-xs overflow-hidden font-mono p-4">
{glitchText}
{glitchText}
{glitchText}
{glitchText}
{glitchText}
</pre>
{/* Error messages */}
<div className="absolute inset-0 flex flex-col items-center justify-center">
{errorMessages.slice(0, Math.min(phase + 1, errorMessages.length)).map((msg, i) => (
<motion.div
key={i}
initial={{ opacity: 0, x: Math.random() * 200 - 100 }}
animate={{
opacity: [0, 1, 1, 0.5],
x: [Math.random() * 100 - 50, 0, Math.random() * 50 - 25],
}}
transition={{ duration: 0.5 }}
className="font-minecraft text-xl md:text-3xl text-destructive mb-2"
style={{
textShadow: '0 0 10px currentColor, 0 0 20px currentColor',
transform: `rotate(${Math.random() * 10 - 5}deg)`,
}}
>
{msg}
</motion.div>
))}
</div>
{/* Final message */}
{phase > 6 && (
<motion.div
initial={{ scale: 0 }}
animate={{ scale: [0, 1.2, 1] }}
className="absolute inset-0 flex items-center justify-center"
>
<div className="text-center">
<div className="font-minecraft text-4xl md:text-6xl text-primary text-glow-strong mb-4">
SYSTEM OVERFLOW
</div>
<div className="font-pixel text-lg text-foreground/80">
You broke the matrix. Congratulations.
</div>
<div className="font-pixel text-sm text-foreground/50 mt-4">
(Refreshing in a moment...)
</div>
</div>
</motion.div>
)}
{/* Glitch bars */}
{Array.from({ length: 10 }).map((_, i) => (
<div
key={i}
className="absolute bg-primary/50"
style={{
left: `${Math.random() * 100}%`,
top: `${Math.random() * 100}%`,
width: `${Math.random() * 300 + 50}px`,
height: `${Math.random() * 20 + 2}px`,
animation: `glitchShake ${0.1 + Math.random() * 0.2}s infinite`,
opacity: Math.random(),
}}
/>
))}
</motion.div>
);
};
export default GlitchCrash;