one/frontend/src/components/CustomCircleCursor.tsx
Ameya Shenoy e74f75ae4b feat: portfolio done + minimal working blog
Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
2025-06-23 09:22:26 +05:30

79 lines
2.3 KiB
TypeScript

"use client";
import { useRef, useEffect, FC, useState } from "react";
import gsap from "gsap";
const GSAPCursor: FC = () => {
const cursorRef = useRef<HTMLDivElement>(null);
const [position, setPosition] = useState({ x: 0, y: 0 });
const [isHoveringLink, setIsHoveringLink] = useState(false);
// For touch devices, return null
if (typeof window !== "undefined" && "ontouchstart" in window) return null;
useEffect(() => {
// Initialize GSAP animation
let xTo = gsap.quickTo(cursorRef.current, "x", {
duration: 2,
ease: "power2.out",
});
let yTo = gsap.quickTo(cursorRef.current, "y", {
duration: 2,
ease: "power2.out",
});
const onMouseMove = (e: MouseEvent) => {
xTo(e.clientX);
yTo(e.clientY);
};
window.addEventListener("mousemove", onMouseMove);
const handleMouseOver = () => setIsHoveringLink(true);
const handleMouseOut = () => setIsHoveringLink(false);
const links = document.querySelectorAll('a');
links.forEach(link => {
link.addEventListener('mouseover', handleMouseOver);
link.addEventListener('mouseout', handleMouseOut);
});
return () => {
links.forEach(link => {
link.removeEventListener('mouseover', handleMouseOver);
link.removeEventListener('mouseout', handleMouseOut);
});
window.removeEventListener("mousemove", onMouseMove);
};
}, []);
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
setPosition({ x: e.clientX, y: e.clientY });
};
window.addEventListener("mousemove", handleMouseMove);
return () => window.removeEventListener("mousemove", handleMouseMove);
}, []);
return (
<div>
<div
ref={cursorRef}
className={`fixed w-8 h-8 ${isHoveringLink ? 'rounded-none' : 'rounded-full'} border-2 border-dotted border-red-500 bg-transparent pointer-events-none z-60`}
style={{
transform: "translate(-50%, -50%)",
}}
/>
<div
className="fixed w-2 h-2 rounded-full bg-black dark:bg-white pointer-events-none z-60"
style={{
left: `${position.x}px`,
top: `${position.y}px`,
transform: "translate(-50%, -50%)", // Centers the dot on the cursor
}}
/>
</div>
);
};
export default GSAPCursor;