Glitch 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-nocheck2'use client';34import { useState, useEffect } from 'react';5import { useMouse } from '@/hooks/use-mouse';67const GlitchCursor = () => {8const [mouseState, ref] = useMouse();9const [glitchActive, setGlitchActive] = useState(false);10const [glitchOffsets, setGlitchOffsets] = useState([]);11const [intensity, setIntensity] = useState(1);1213useEffect(() => {14let interval;15if (glitchActive) {16interval = setInterval(() => {17const newOffsets = Array(5)18.fill(0)19.map(() => ({20x: (Math.random() - 0.5) * 20 * intensity,21y: (Math.random() - 0.5) * 20 * intensity,22scale: 0.8 + Math.random() * 0.4,23rotation: (Math.random() - 0.5) * 45 * intensity,24opacity: 0.5 + Math.random() * 0.5,25hue: Math.random() * 360,26}));27setGlitchOffsets(newOffsets);28}, 50);29} else {30setGlitchOffsets([]);31}32return () => clearInterval(interval);33}, [glitchActive, intensity]);3435const handleMouseSpeed = (e) => {36const speed = Math.sqrt(37Math.pow(e.movementX, 2) + Math.pow(e.movementY, 2)38);39setIntensity(Math.min(Math.max(speed / 10, 1), 3));40};4142return (43<div44className='relative w-full h-full '45ref={ref}46onMouseMove={handleMouseSpeed}47>48{mouseState.x !== null && mouseState.y !== null && (49<>50{/* Glitch layers */}51{glitchOffsets.map((offset, index) => (52<div53key={index}54className='fixed pointer-events-none mix-blend-screen'55style={{56left: mouseState.x + offset.x,57top: mouseState.y + offset.y,58transform: `translate(-50%, -50%)59scale(${offset.scale})60rotate(${offset.rotation}deg)`,61opacity: offset.opacity,62}}63>64<div65className='w-8 h-8 rounded-full'66style={{67background: `hsl(${offset.hue}, 100%, 50%)`,68filter: 'blur(2px)',69}}70/>71</div>72))}7374{/* Main cursor */}75<div76className='fixed pointer-events-none z-50'77style={{78left: mouseState.x,79top: mouseState.y,80transform: 'translate(-50%, -50%)',81}}82>83<div className='w-8 h-8 bg-white rounded-full mix-blend-screen' />84</div>8586{/* Static effect overlay */}87{glitchActive && (88<div89className='fixed pointer-events-none mix-blend-screen'90style={{91left: mouseState.x,92top: mouseState.y,93transform: 'translate(-50%, -50%)',94width: '100px',95height: '100px',96background: `url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100' height='100' filter='url(%23noise)' opacity='0.5'/%3E%3C/svg%3E")`,97opacity: 0.3,98}}99/>100)}101</>102)}103104<div className='flex flex-col items-center justify-center h-full gap-8'>105<button106className={`px-8 py-4 bg-red-600/30 text-white rounded-lg transition-all duration-300 relative overflow-hidden107${glitchActive ? 'animate-pulse' : ''}`}108onMouseEnter={() => setGlitchActive(true)}109onMouseLeave={() => setGlitchActive(false)}110>111Trigger Glitch112{glitchActive && (113<div className='absolute inset-0 bg-red-500/20 animate-glitch-overlay' />114)}115</button>116</div>117118<style>{`119@keyframes glitch-overlay {1200% { transform: translateX(0); }12125% { transform: translateX(-5px); }12250% { transform: translateX(5px); }12375% { transform: translateX(-2px); }124100% { transform: translateX(0); }125}126`}</style>127</div>128);129};130131export default GlitchCursor;132
1'use client';2import { type RefObject, useLayoutEffect, useRef, useState } from 'react';34interface MouseState {5x: number | null;6y: number | null;7elementX: number | null;8elementY: number | null;9elementPositionX: number | null;10elementPositionY: number | null;11}1213export function useMouse(): [MouseState, RefObject<HTMLDivElement>] {14const [state, setState] = useState<MouseState>({15x: null,16y: null,17elementX: null,18elementY: null,19elementPositionX: null,20elementPositionY: null,21});2223const ref = useRef<HTMLDivElement | null>(null);2425useLayoutEffect(() => {26const handleMouseMove = (event: MouseEvent) => {27const newState: Partial<MouseState> = {28x: event.pageX,29y: event.pageY,30};3132if (ref.current instanceof Element) {33const { left, top } = ref.current.getBoundingClientRect();34const elementPositionX = left + window.scrollX;35const elementPositionY = top + window.scrollY;36const elementX = event.pageX - elementPositionX;37const elementY = event.pageY - elementPositionY;3839newState.elementX = elementX;40newState.elementY = elementY;41newState.elementPositionX = elementPositionX;42newState.elementPositionY = elementPositionY;43}4445setState((s) => ({46...s,47...newState,48}));49};5051document.addEventListener('mousemove', handleMouseMove);5253return () => {54document.removeEventListener('mousemove', handleMouseMove);55};56}, []);5758return [state, ref];59}