Flair Cursor Follower
Hover your Cursor
Installation
bash
pnpm add gsap
Usage
tsx
1import FlairCursorFollower from './FlairCursorFollower'23// usage4<FlairCursorFollower />
Code
tsx
1"use client";23import React, { useEffect, useMemo, useRef } from "react";4import { gsap } from "gsap";56export const FlairCursorFollower: React.FC = () => {7 const indexRef = useRef(0);8 const nodesRef = useRef<HTMLImageElement[]>([]);910 // β gate distance11 const lastSpawnPosRef = useRef<{ x: number; y: number } | null>(null);12 const gapRef = useRef(100); // π atur: 80β140 biasanya enak1314 const imgList = useMemo(15 () => [16 "https://assets.codepen.io/16327/Revised+Flair.png",17 "https://assets.codepen.io/16327/Revised+Flair-1.png",18 "https://assets.codepen.io/16327/Revised+Flair-2.png",19 "https://assets.codepen.io/16327/Revised+Flair-3.png",20 "https://assets.codepen.io/16327/Revised+Flair-4.png",21 "https://assets.codepen.io/16327/Revised+Flair-5.png",22 "https://assets.codepen.io/16327/Revised+Flair-6.png",23 "https://assets.codepen.io/16327/Revised+Flair-7.png",24 "https://assets.codepen.io/16327/Revised+Flair-8.png",25 "https://assets.codepen.io/16327/Revised+Flair.png",26 "https://assets.codepen.io/16327/Revised+Flair-1.png",27 "https://assets.codepen.io/16327/Revised+Flair-2.png",28 "https://assets.codepen.io/16327/Revised+Flair-3.png",29 "https://assets.codepen.io/16327/Revised+Flair-4.png",30 "https://assets.codepen.io/16327/Revised+Flair-5.png",31 "https://assets.codepen.io/16327/Revised+Flair-6.png",32 "https://assets.codepen.io/16327/Revised+Flair-7.png",33 "https://assets.codepen.io/16327/Revised+Flair-8.png",34 ],35 []36 );3738 useEffect(() => {39 nodesRef.current = Array.from(40 document.querySelectorAll<HTMLImageElement>(".flair")41 );42 if (nodesRef.current.length === 0) return;4344 gsap.set(nodesRef.current, {45 opacity: 0,46 xPercent: -50,47 yPercent: -50,48 });4950 const spawn = (x: number, y: number) => {51 const nodes = nodesRef.current;52 if (nodes.length === 0) return;5354 const i = indexRef.current % nodes.length;55 const img = nodes[i];56 if (!img) return;57 indexRef.current += 1;5859 gsap.killTweensOf(img);6061 gsap.set(img, {62 opacity: 1,63 left: x,64 top: y,65 rotation: 0,66 scale: 1,67 y: 0,68 position: "fixed",69 });7071 gsap72 .timeline()73 .fromTo(74 img,75 { scale: 0.6 },76 { scale: 1, duration: 0.15, ease: "power2.out" }77 )78 .to(img, { rotation: gsap.utils.random(-360, 360), duration: 0.6 }, "<")79 .to(80 img,81 { y: window.innerHeight * 1.2, duration: 1, ease: "power2.in" },82 083 )84 .to(img, { opacity: 0, duration: 0.4 }, 0.6);85 };8687 const onMove = (e: MouseEvent) => {88 const x = e.clientX;89 const y = e.clientY;9091 // init pos pertama kali92 if (!lastSpawnPosRef.current) {93 lastSpawnPosRef.current = { x, y };94 return;95 }9697 const dx = x - lastSpawnPosRef.current.x;98 const dy = y - lastSpawnPosRef.current.y;99 const dist = Math.hypot(dx, dy);100101 // β hanya spawn kalau gerak sudah cukup jauh102 if (dist < gapRef.current) return;103104 spawn(x, y);105 lastSpawnPosRef.current = { x, y };106 };107108 window.addEventListener("mousemove", onMove);109110 return () => {111 window.removeEventListener("mousemove", onMove);112 for (const el of nodesRef.current) gsap.killTweensOf(el);113 };114 }, []);115116 return (117 <div118 className="pointer-events-none fixed inset-0 z-50 overflow-hidden"119 aria-hidden="true"120 >121 {imgList.map((src, i) => (122 <img123 key={i}124 src={src}125 alt=""126 className="flair"127 style={{128 position: "fixed",129 opacity: 0,130 width: "50px",131 left: 0,132 top: 0,133 pointerEvents: "none",134 }}135 />136 ))}137 </div>138 );139};140141/**142 Arctis UI Component β <FlairCursorFollower>143144 Created with π by Ranaufal Muha145 https://ranaufalmuha.com146147 Hi! Thank you for using this component.148 Youβre free to copy, modify, or use it in any project you like.149150 If possible, please keep this small header as appreciation.151 It helps others know where the component came from β€οΈ152153 Usage:154 import { FlairCursorFollower } from "@arctis/ui";155156 // usage157 <FlairCursorFollower />158159 */








