Add src/components/cursor/CustomCursor.tsx

This commit is contained in:
2026-03-21 09:20:19 +00:00
parent 59968ad77f
commit 26a8eea132

View File

@@ -0,0 +1,91 @@
"use client";
import { useEffect, useRef } from "react";
const CustomCursor = () => {
const cursorRef = useRef<HTMLDivElement>(null);
const followerRef = useRef<HTMLDivElement>(null);
const mousePosition = useRef({ x: 0, y: 0 });
const followerPosition = useRef({ x: 0, y: 0 });
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
mousePosition.current = { x: e.clientX, y: e.clientY };
if (cursorRef.current) {
cursorRef.current.style.left = `${e.clientX}px`;
cursorRef.current.style.top = `${e.clientY}px`;
}
};
const animateFollower = () => {
const dx =
mousePosition.current.x - followerPosition.current.x;
const dy =
mousePosition.current.y - followerPosition.current.y;
followerPosition.current.x += dx * 0.15;
followerPosition.current.y += dy * 0.15;
if (followerRef.current) {
followerRef.current.style.left = `${followerPosition.current.x}px`;
followerRef.current.style.top = `${followerPosition.current.y}px`;
}
requestAnimationFrame(animateFollower);
};
const handleMouseEnter = () => {
if (cursorRef.current) {
cursorRef.current.style.opacity = "1";
}
if (followerRef.current) {
followerRef.current.style.opacity = "1";
}
};
const handleMouseLeave = () => {
if (cursorRef.current) {
cursorRef.current.style.opacity = "0";
}
if (followerRef.current) {
followerRef.current.style.opacity = "0";
}
};
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseenter", handleMouseEnter);
window.addEventListener("mouseleave", handleMouseLeave);
animateFollower();
return () => {
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseenter", handleMouseEnter);
window.removeEventListener("mouseleave", handleMouseLeave);
};
}, []);
return (
<>
<div
ref={cursorRef}
className="pointer-events-none fixed z-50 w-3 h-3 bg-primary-cta rounded-full shadow-lg mix-blend-screen opacity-0 transition-opacity duration-300"
style={{
transform: "translate(-50%, -50%)"}}
/>
<div
ref={followerRef}
className="pointer-events-none fixed z-40 w-8 h-8 border-2 border-primary-cta rounded-full opacity-0 transition-opacity duration-300"
style={{
transform: "translate(-50%, -50%)", boxShadow: "0 0 20px rgba(var(--primary-cta-rgb), 0.3)"}}
/>
<style>{`
* {
cursor: none !important;
}
`}</style>
</>
);
};
export default CustomCursor;