Files
novalon-website/src/components/effects/gradient-orbs.tsx
T
张翔 fecbfd1990 feat: 添加预览效果页面并优化交互效果
refactor: 优化代码健壮性和类型安全

style: 更新字体样式和全局CSS

fix: 修复IntersectionObserver潜在空引用问题

chore: 更新依赖和ESLint配置

build: 更新构建ID和路由配置
2026-02-24 10:24:05 +08:00

93 lines
2.4 KiB
TypeScript

'use client';
import { motion, useReducedMotion } from 'framer-motion';
import { useEffect, useState } from 'react';
interface GradientOrbsProps {
className?: string;
count?: number;
}
interface Orb {
id: number;
size: number;
x: number;
y: number;
color: string;
duration: number;
delay: number;
}
const colorPalette = [
'rgba(196, 30, 58, 0.15)',
'rgba(255, 232, 236, 0.2)',
'rgba(255, 240, 243, 0.18)',
'rgba(245, 245, 245, 0.15)',
'rgba(255, 214, 221, 0.2)',
'rgba(224, 74, 104, 0.12)',
];
export function GradientOrbs({ className = '', count = 5 }: GradientOrbsProps) {
const prefersReducedMotion = useReducedMotion();
const [orbs, setOrbs] = useState<Orb[]>([]);
useEffect(() => {
const generatedOrbs: Orb[] = Array.from({ length: count }, (_, i) => ({
id: i,
size: Math.random() * 400 + 200,
x: Math.random() * 100,
y: Math.random() * 100,
color: colorPalette[i % colorPalette.length] ?? 'rgba(196, 30, 58, 0.15)',
duration: Math.random() * 20 + 15,
delay: Math.random() * 5,
}));
setOrbs(generatedOrbs);
}, [count]);
return (
<div
className={`absolute inset-0 overflow-hidden ${className}`}
aria-hidden="true"
>
{orbs.map((orb) => (
<motion.div
key={orb.id}
className="absolute rounded-full"
style={{
width: orb.size,
height: orb.size,
left: `${orb.x}%`,
top: `${orb.y}%`,
background: `radial-gradient(circle, ${orb.color} 0%, transparent 70%)`,
willChange: prefersReducedMotion ? 'auto' : 'transform',
filter: 'blur(60px)',
}}
initial={{
x: '-50%',
y: '-50%',
scale: 1,
}}
animate={
prefersReducedMotion
? {}
: {
x: ['-50%', '-40%', '-60%', '-50%'],
y: ['-50%', '-60%', '-40%', '-50%'],
scale: [1, 1.2, 0.9, 1],
}
}
transition={{
duration: orb.duration,
repeat: Infinity,
ease: 'easeInOut',
delay: orb.delay,
}}
/>
))}
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-white/20 pointer-events-none" />
</div>
);
}
export default GradientOrbs;