File size: 2,130 Bytes
c4e3b10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

import React, { useEffect, useContext } from 'react';
import { gsap } from 'gsap';
import { ThemeContext } from '../App';

const CustomCursor: React.FC = () => {
  const { theme } = useContext(ThemeContext);

  useEffect(() => {
    const cursor = document.querySelector('.cursor');
    const follower = document.querySelector('.cursor-follower');

    if (!cursor || !follower) return;

    gsap.set(cursor, { xPercent: -50, yPercent: -50 });
    gsap.set(follower, { xPercent: -50, yPercent: -50 });

    const pos = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
    const mouse = { x: pos.x, y: pos.y };
    const speed = 0.1;

    const xSet = gsap.quickSetter(cursor, "x", "px");
    const ySet = gsap.quickSetter(cursor, "y", "px");
    const xSetFollower = gsap.quickSetter(follower, "x", "px");
    const ySetFollower = gsap.quickSetter(follower, "y", "px");

    const mouseMove = (e: MouseEvent) => {
      mouse.x = e.clientX;
      mouse.y = e.clientY;
    };

    const animation = () => {
      const dt = 1.0 - Math.pow(1.0 - speed, gsap.ticker.deltaRatio());
      pos.x += (mouse.x - pos.x) * dt;
      pos.y += (mouse.y - pos.y) * dt;
      xSet(mouse.x);
      ySet(mouse.y);
      xSetFollower(pos.x);
      ySetFollower(pos.y);
    };

    window.addEventListener("mousemove", mouseMove);
    gsap.ticker.add(animation);

    return () => {
      window.removeEventListener("mousemove", mouseMove);
      gsap.ticker.remove(animation);
    };
  }, []);

  const accentColor = theme === 'dark' ? 'border-[#00ffff]' : 'border-[#0066cc]';
  const followerBg = theme === 'dark' ? 'bg-[radial-gradient(circle,_#00ffff,_transparent)]' : 'bg-[radial-gradient(circle,_#0066cc,_transparent)]';

  return (
    <div className="hidden md:block">
      <div className={`cursor fixed w-5 h-5 rounded-full pointer-events-none z-[9999] mix-blend-difference transition-colors duration-300 ${accentColor}`}></div>
      <div className={`cursor-follower fixed w-10 h-10 rounded-full pointer-events-none z-[9998] transition-colors duration-300 ${followerBg}`}></div>
    </div>
  );
};

export default CustomCursor;