76
components/FairyDust.tsx
Normal file
76
components/FairyDust.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
id: number;
|
||||
size: number;
|
||||
color: string;
|
||||
velocity: { x: number; y: number };
|
||||
life: number;
|
||||
}
|
||||
|
||||
export const FairyDust: React.FC = () => {
|
||||
const [points, setPoints] = useState<Point[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
const colors = ['#FF00CC', '#3333FF', '#7000FF', '#FFFFFF', '#00FFFF'];
|
||||
const newPoint: Point = {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
id: Date.now() + Math.random(),
|
||||
size: Math.random() * 4 + 2,
|
||||
color: colors[Math.floor(Math.random() * colors.length)],
|
||||
velocity: {
|
||||
x: (Math.random() - 0.5) * 2,
|
||||
y: (Math.random() - 0.5) * 2
|
||||
},
|
||||
life: 1.0
|
||||
};
|
||||
setPoints(prev => [...prev.slice(-40), newPoint]); // Limit trail length
|
||||
};
|
||||
|
||||
window.addEventListener('mousemove', handleMouseMove);
|
||||
return () => window.removeEventListener('mousemove', handleMouseMove);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setPoints(prev => prev
|
||||
.map(p => ({
|
||||
...p,
|
||||
x: p.x + p.velocity.x,
|
||||
y: p.y + p.velocity.y,
|
||||
life: p.life - 0.05
|
||||
}))
|
||||
.filter(p => p.life > 0)
|
||||
);
|
||||
}, 16); // 60fps
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 pointer-events-none z-[9999]">
|
||||
{points.map(point => (
|
||||
<div
|
||||
key={point.id}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: point.x,
|
||||
top: point.y,
|
||||
width: point.size,
|
||||
height: point.size,
|
||||
backgroundColor: point.color,
|
||||
borderRadius: '50%',
|
||||
opacity: point.life,
|
||||
transform: `scale(${point.life})`,
|
||||
boxShadow: `0 0 ${point.size * 2}px ${point.color}`,
|
||||
transition: 'opacity 0.1s linear'
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user