62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
// components/InteractiveTopo.tsx
|
|
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
|
|
export default function InteractiveTopo() {
|
|
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
|
|
|
|
useEffect(() => {
|
|
const handleMouseMove = (e: MouseEvent) => {
|
|
// Normalize mouse position to percentage
|
|
const x = (e.clientX / window.innerWidth) * 100;
|
|
const y = (e.clientY / window.innerHeight) * 100;
|
|
setMousePosition({ x, y });
|
|
};
|
|
|
|
window.addEventListener('mousemove', handleMouseMove);
|
|
return () => window.removeEventListener('mousemove', handleMouseMove);
|
|
}, []);
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 pointer-events-none z-0 opacity-30"
|
|
style={{
|
|
background: `
|
|
radial-gradient(
|
|
circle at ${mousePosition.x}% ${mousePosition.y}%,
|
|
rgba(255, 255, 255, 0.03) 0%,
|
|
transparent 50%
|
|
)
|
|
`,
|
|
transition: 'background 0.3s ease-out',
|
|
}}
|
|
>
|
|
{/* Animated grid that warps around mouse */}
|
|
<div
|
|
className="absolute inset-0"
|
|
style={{
|
|
backgroundImage: `
|
|
repeating-linear-gradient(
|
|
0deg,
|
|
transparent,
|
|
transparent 50px,
|
|
rgba(255, 255, 255, 0.02) 50px,
|
|
rgba(255, 255, 255, 0.02) 51px
|
|
),
|
|
repeating-linear-gradient(
|
|
90deg,
|
|
transparent,
|
|
transparent 50px,
|
|
rgba(255, 255, 255, 0.02) 50px,
|
|
rgba(255, 255, 255, 0.02) 51px
|
|
)
|
|
`,
|
|
transform: `translate(${(mousePosition.x - 50) * 0.02}px, ${(mousePosition.y - 50) * 0.02}px)`,
|
|
transition: 'transform 0.3s ease-out',
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|