AnimatedCursors.tsx61 lines · main
1import { motion } from 'framer-motion'
2import { MousePointer2 } from 'lucide-react'
3import { useEffect, useState } from 'react'
4
5export const AnimatedCursors = () => {
6 const [cursor1Position, setCursor1Position] = useState({ x: 20, y: 20 })
7 const [cursor2Position, setCursor2Position] = useState({ x: 180, y: 80 })
8
9 useEffect(() => {
10 const animateCursors = () => {
11 const newCursor1Position = {
12 x: Math.random() * 160 + 20,
13 y: Math.random() * 80 + 20,
14 }
15 const newCursor2Position = {
16 x: Math.random() * 160 + 20,
17 y: Math.random() * 80 + 20,
18 }
19
20 setCursor1Position(newCursor1Position)
21 setCursor2Position(newCursor2Position)
22 }
23
24 const initialTimer = setTimeout(animateCursors, 1000)
25
26 const interval = setInterval(animateCursors, 3000)
27
28 return () => {
29 clearTimeout(initialTimer)
30 clearInterval(interval)
31 }
32 }, [])
33
34 return (
35 <div className="relative w-48 h-32 mx-auto mb-8">
36 <motion.div
37 className="absolute text-warning"
38 animate={{ x: cursor1Position.x, y: cursor1Position.y }}
39 transition={{
40 duration: 1.2,
41 ease: 'easeInOut',
42 }}
43 style={{ width: 20, height: 20 }}
44 >
45 <MousePointer2 size={20} />
46 </motion.div>
47 <motion.div
48 className="absolute text-brand"
49 animate={{ x: cursor2Position.x, y: cursor2Position.y }}
50 transition={{
51 duration: 1.2,
52 ease: 'easeInOut',
53 delay: 0.2,
54 }}
55 style={{ width: 20, height: 20 }}
56 >
57 <MousePointer2 size={20} />
58 </motion.div>
59 </div>
60 )
61}