Click Cursor Effect
An interactive React component that adds a dynamic bubble effect, visually tracking cursor movement in real time.
An interactive React component that adds a dynamic bubble effect, visually tracking cursor movement in real time.
1// @ts-nocheck23'use client';45import React, { useState, useEffect } from 'react';6import { motion, AnimatePresence } from 'framer-motion';78const ClickEffectCursor = () => {9const [mousePosition, setMousePosition] = useState({ x: null, y: null });10const [clicks, setClicks] = useState([]);11const [isHovering, setIsHovering] = useState(false);12const [trail, setTrail] = useState([]);1314// Handle mouse movement15useEffect(() => {16const updateMousePosition = (e) => {17setMousePosition({ x: e.clientX, y: e.clientY });1819// Add point to trail20setTrail((prev) => [21...prev.slice(-20),22{ x: e.clientX, y: e.clientY, id: Date.now() },23]);24};2526window.addEventListener('mousemove', updateMousePosition);27return () => window.removeEventListener('mousemove', updateMousePosition);28}, []);2930const handleClick = (e) => {31const newClick = {32x: e.clientX,33y: e.clientY,34id: Date.now(),35};36setClicks((prev) => [...prev, newClick]);3738// Remove click effect after animation39setTimeout(() => {40setClicks((prev) => prev.filter((click) => click.id !== newClick.id));41}, 1000);42};4344return (45<div46className='w-full bg-black'47onClick={handleClick}48onMouseEnter={() => setIsHovering(true)}49onMouseLeave={() => setIsHovering(false)}50>51{/* Mouse trail */}52<AnimatePresence>53{trail.map((point, index) => (54<motion.div55key={point.id}56className='fixed pointer-events-none'57initial={{ scale: 1, opacity: 0.5 }}58animate={{ scale: 0, opacity: 0 }}59exit={{ opacity: 0 }}60style={{61left: point.x,62top: point.y,63transform: 'translate(-50%, -50%)',64}}65transition={{ duration: 0.5 }}66>67<div68className='w-2 h-2 bg-pink-400 rounded-full'69style={{70opacity: (index / trail.length) * 0.5,71}}72/>73</motion.div>74))}75</AnimatePresence>7677{/* Main cursor */}78{mousePosition.x !== null && mousePosition.y !== null && (79<motion.div80className='fixed pointer-events-none z-50'81animate={{82x: mousePosition.x,83y: mousePosition.y,84scale: isHovering ? 1.5 : 1,85}}86transition={{87type: 'spring',88stiffness: 500,89damping: 28,90mass: 0.5,91}}92style={{93transform: 'translate(-50%, -50%)',94}}95>96<div className='relative'>97<div className='w-6 h-6 bg-pink-500 rounded-full mix-blend-screen' />98<div className='absolute inset-0 w-6 h-6 border-2 border-pink-300 rounded-full animate-ping' />99</div>100</motion.div>101)}102103{/* Click effects */}104<AnimatePresence>105{clicks.map((click) => (106<React.Fragment key={click.id}>107{/* Ripple effect */}108<motion.div109className='fixed pointer-events-none'110style={{111left: click.x,112top: click.y,113transform: 'translate(-50%, -50%)',114}}115initial={{ scale: 0, opacity: 1 }}116animate={{ scale: 2.5, opacity: 0 }}117exit={{ opacity: 0 }}118transition={{ duration: 0.8, ease: 'easeOut' }}119>120<div className='w-12 h-12 border-2 border-pink-400 rounded-full' />121</motion.div>122123{/* Particle explosion */}124{[...Array(12)].map((_, i) => (125<motion.div126key={i}127className='fixed pointer-events-none w-2 h-2 bg-gradient-to-r from-pink-400 to-purple-500 rounded-full'128style={{129left: click.x,130top: click.y,131}}132initial={{ scale: 0 }}133animate={{134scale: [0, 1, 0],135x: Math.cos((i * Math.PI) / 6) * 80,136y: Math.sin((i * Math.PI) / 6) * 80,137opacity: [1, 0],138}}139transition={{140duration: 0.6,141ease: 'easeOut',142times: [0, 0.2, 1],143}}144/>145))}146</React.Fragment>147))}148</AnimatePresence>149</div>150);151};152153export default ClickEffectCursor;154
1npm install framer-motion