Magnetic Cursor Effect
An interactive React component that creates magnetic attraction effects when cursor approaches elements with smooth spring physics.
An interactive React component that creates magnetic attraction effects when cursor approaches elements with smooth spring physics.
1'use client';2import { useRef, useEffect, useState, useCallback, ReactNode } from 'react';3import { motion, useMotionValue, useSpring } from 'framer-motion';4import { cn } from '@/lib/utils';56interface MagneticProps {7magneticDistance?: number;8strength?: number;9stiffness?: number;10damping?: number;11children: ReactNode | ((isHovering: boolean) => ReactNode);12}1314function Magnetic({15magneticDistance = 200,16strength = 0.9,17stiffness = 80,18damping = 10,19children,20}: MagneticProps) {21const ref = useRef<HTMLDivElement>(null);22const x = useMotionValue(0);23const y = useMotionValue(0);24const springX = useSpring(x, { stiffness, damping });25const springY = useSpring(y, { stiffness, damping });26const [isHovering, setIsHovering] = useState(false);2728const onMouseMove = useCallback(29(e: MouseEvent) => {30if (!ref.current) return;31const rect = ref.current.getBoundingClientRect();32const cx = rect.left + rect.width / 2;33const cy = rect.top + rect.height / 2;34const dx = e.clientX - cx;35const dy = e.clientY - cy;36const dist = Math.sqrt(dx * dx + dy * dy);3738if (dist < magneticDistance) {39const pull = Math.pow(1 - dist / magneticDistance, 0.5);40x.set(dx * pull * strength);41y.set(dy * pull * strength);42setIsHovering(true);43} else {44x.set(0);45y.set(0);46setIsHovering(false);47}48},49[x, y, magneticDistance, strength]50);5152useEffect(() => {53window.addEventListener('mousemove', onMouseMove);54return () => window.removeEventListener('mousemove', onMouseMove);55}, [onMouseMove]);5657return (58<motion.div59ref={ref}60style={{ x: springX, y: springY, display: 'inline-block' }}61>62{typeof children === 'function' ? children(isHovering) : children}63</motion.div>64);65}6667export default function MagneticCursor() {68return (69<div className='grid place-items-center h-full'>70<Magnetic>71{(hovering) => (72<button73onClick={() => alert('clicked!')}74className={cn(75`76w-36 h-36 border-red-500 border rounded-full text-xs tracking-widest uppercase font-semibold77cursor-pointer transition-all duration-400 outline-none7879`,80hovering81? 'shadow-[0_0_60px_rgba(255,140,120,0.45),0_0_120px_rgba(255,140,120,0.15)]'82: 'shadow-[0_4px_28px_rgba(255,140,120,0.22)]',83hovering && 'scale-105 bg-red-500 text-white'84)}85>86ENTER87</button>88)}89</Magnetic>90</div>91);92}93
1npm install motion