spotify/src/components/AnimatedBackground.tsx
2025-10-14 14:08:06 +02:00

164 lines
4.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import { motion } from 'framer-motion';
import { InteractiveBubbles } from './InteractiveBubbles';
interface Particle {
id: number;
x: number;
y: number;
size: number;
speed: number;
delay: number;
}
export const AnimatedBackground = () => {
const [particles, setParticles] = useState<Particle[]>([]);
useEffect(() => {
const createParticles = () => {
const newParticles: Particle[] = [];
for (let i = 0; i < 50; i++) {
newParticles.push({
id: i,
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
size: Math.random() * 4 + 2,
speed: Math.random() * 0.5 + 0.1,
delay: Math.random() * 5,
});
}
setParticles(newParticles);
};
createParticles();
const handleResize = () => {
createParticles();
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<div className="fixed inset-0 pointer-events-none overflow-hidden">
{/* Large liquid light cylinders from top */}
<div className="light-cylinder light-cylinder-1"></div>
<div className="light-cylinder light-cylinder-2"></div>
<div className="light-cylinder light-cylinder-3"></div>
{/* Fluid wave bubbles */}
<div className="wave-bubble"></div>
<div className="wave-bubble"></div>
<div className="wave-bubble"></div>
<div className="wave-bubble"></div>
<div className="wave-bubble"></div>
{/* Animated particles */}
{particles.map((particle) => (
<motion.div
key={particle.id}
className="absolute rounded-full bg-gradient-to-br from-purple-500/20 via-blue-500/20 to-pink-500/20"
style={{
width: particle.size,
height: particle.size,
left: particle.x,
top: particle.y,
}}
animate={{
y: [particle.y, particle.y - 100],
opacity: [0, 1, 0],
scale: [0, 1, 0],
}}
transition={{
duration: 10 + particle.speed * 10,
delay: particle.delay,
repeat: Infinity,
ease: "linear",
}}
/>
))}
{/* Interactive bubbles */}
<InteractiveBubbles />
{/* Floating musical notes */}
<motion.div
className="absolute top-20 left-10 text-2xl text-spotify-green/30"
animate={{
y: [0, -20, 0],
rotate: [0, 10, -10, 0],
}}
transition={{
duration: 4,
repeat: Infinity,
ease: "easeInOut",
}}
>
</motion.div>
<motion.div
className="absolute top-40 right-20 text-3xl text-spotify-green/20"
animate={{
y: [0, -30, 0],
rotate: [0, -15, 15, 0],
}}
transition={{
duration: 6,
repeat: Infinity,
ease: "easeInOut",
delay: 1,
}}
>
</motion.div>
<motion.div
className="absolute bottom-32 left-1/4 text-xl text-spotify-green/25"
animate={{
y: [0, -25, 0],
rotate: [0, 20, -20, 0],
}}
transition={{
duration: 5,
repeat: Infinity,
ease: "easeInOut",
delay: 2,
}}
>
</motion.div>
<motion.div
className="absolute bottom-20 right-1/3 text-2xl text-spotify-green/30"
animate={{
y: [0, -35, 0],
rotate: [0, -25, 25, 0],
}}
transition={{
duration: 7,
repeat: Infinity,
ease: "easeInOut",
delay: 3,
}}
>
</motion.div>
{/* Subtle grid pattern */}
<div
className="absolute inset-0 opacity-10"
style={{
backgroundImage: `
linear-gradient(rgba(29, 185, 84, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(29, 185, 84, 0.1) 1px, transparent 1px)
`,
backgroundSize: '50px 50px',
}}
/>
</div>
);
};