npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aniruddha1806/use-mouse-move

v1.0.1

Published

A lightweight React hook for tracking mouse position with throttling and debouncing

Downloads

10

Readme

React useMouseMove Hook

A powerful React hook for tracking mouse position with support for element-specific coordinates, performance optimization through throttling and debouncing, and boundary detection.

Installation

npm install @aniruddha1806/use-mouse-move

Features

  • 🖱️ Global Mouse Tracking: Track mouse position across the entire viewport
  • 🎯 Element-Specific Tracking: Get mouse coordinates relative to any element
  • Performance Optimized: Built-in throttling and debouncing options
  • 🔍 Boundary Detection: Know when mouse is within element bounds
  • 📱 Responsive: Works with dynamic element sizes and positions
  • 🎨 Flexible: Use for hover effects, drag operations, cursor followers
  • 🪶 Lightweight: Zero dependencies beyond React
  • 🔧 Easy Integration: Simple API with sensible defaults

Quick Start

import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function App() {
  const { x, y } = useMouseMove();
  
  return (
    <div>
      <h1>Mouse Tracker</h1>
      <p>Mouse position: ({x}, {y})</p>
    </div>
  );
}

API

Parameters

The hook accepts an options object with the following properties:

| Option | Type | Default | Description | |--------|------|---------|-------------| | element | RefObject<HTMLElement> | null | Element to track mouse position within | | throttle | number | 0 | Throttle updates in milliseconds (0 = disabled) | | debounce | number | 0 | Debounce updates in milliseconds (0 = disabled) |

Returns

The hook returns an object with the following properties:

| Property | Type | Description | |----------|------|-------------| | x | number | Global mouse X coordinate | | y | number | Global mouse Y coordinate | | elementX | number \| null | Mouse X coordinate relative to element | | elementY | number \| null | Mouse Y coordinate relative to element | | isInBounds | boolean | Whether mouse is within element boundaries |

Examples

Basic Global Mouse Tracking

Track mouse position across the entire viewport:

import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function GlobalMouseTracker() {
  const { x, y } = useMouseMove();
  
  return (
    <div style={{ height: '100vh', padding: '20px' }}>
      <h2>Global Mouse Position</h2>
      <p>X: {x}px</p>
      <p>Y: {y}px</p>
      
      {/* Visual indicator */}
      <div
        style={{
          position: 'fixed',
          left: x - 5,
          top: y - 5,
          width: '10px',
          height: '10px',
          backgroundColor: 'red',
          borderRadius: '50%',
          pointerEvents: 'none',
          zIndex: 9999,
        }}
      />
    </div>
  );
}

Element-Specific Mouse Tracking

Track mouse position relative to a specific element:

import { useRef } from 'react';
import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function ElementMouseTracker() {
  const boxRef = useRef(null);
  const { x, y, elementX, elementY, isInBounds } = useMouseMove({
    element: boxRef
  });
  
  return (
    <div style={{ padding: '20px' }}>
      <h2>Element Mouse Tracking</h2>
      
      <div
        ref={boxRef}
        style={{
          width: '400px',
          height: '300px',
          border: '2px solid #333',
          backgroundColor: isInBounds ? '#e8f5e8' : '#f5f5f5',
          position: 'relative',
          margin: '20px 0',
        }}
      >
        <div style={{ padding: '10px' }}>
          <p>Global: ({x}, {y})</p>
          <p>Element: ({elementX}, {elementY})</p>
          <p>In bounds: {isInBounds ? 'Yes' : 'No'}</p>
        </div>
        
        {/* Show mouse position within element */}
        {isInBounds && (
          <div
            style={{
              position: 'absolute',
              left: elementX - 5,
              top: elementY - 5,
              width: '10px',
              height: '10px',
              backgroundColor: 'blue',
              borderRadius: '50%',
              pointerEvents: 'none',
            }}
          />
        )}
      </div>
    </div>
  );
}

Performance Optimization with Throttling

Use throttling to limit update frequency for better performance:

import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function ThrottledMouseTracker() {
  // Update position at most every 16ms (~60fps)
  const { x, y } = useMouseMove({ throttle: 16 });
  
  return (
    <div style={{ height: '100vh', padding: '20px' }}>
      <h2>Throttled Mouse Tracking (60fps)</h2>
      <p>Position: ({x}, {y})</p>
      <p>Updates are throttled to ~60fps for smooth performance</p>
      
      {/* Smooth following cursor */}
      <div
        style={{
          position: 'fixed',
          left: x - 25,
          top: y - 25,
          width: '50px',
          height: '50px',
          backgroundColor: 'rgba(0, 123, 255, 0.7)',
          borderRadius: '50%',
          pointerEvents: 'none',
          transition: 'transform 0.1s ease-out',
          transform: 'scale(1)',
        }}
      />
    </div>
  );
}

Debounced Mouse Tracking

Use debouncing to delay updates until mouse stops moving:

import { useState } from 'react';
import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function DebouncedMouseTracker() {
  const [lastStoppedPosition, setLastStoppedPosition] = useState({ x: 0, y: 0 });
  
  // Update position only after mouse stops moving for 300ms
  const { x, y } = useMouseMove({ debounce: 300 });
  
  // Update stopped position when debounced position changes
  React.useEffect(() => {
    setLastStoppedPosition({ x, y });
  }, [x, y]);
  
  return (
    <div style={{ height: '100vh', padding: '20px' }}>
      <h2>Debounced Mouse Tracking</h2>
      <p>Move your mouse around and stop...</p>
      <p>Last stopped position: ({lastStoppedPosition.x}, {lastStoppedPosition.y})</p>
      
      {/* Show marker where mouse last stopped */}
      <div
        style={{
          position: 'fixed',
          left: lastStoppedPosition.x - 10,
          top: lastStoppedPosition.y - 10,
          width: '20px',
          height: '20px',
          backgroundColor: 'green',
          borderRadius: '50%',
          pointerEvents: 'none',
        }}
      />
    </div>
  );
}

Interactive Hover Effects

Create interactive hover effects using element tracking:

import { useRef } from 'react';
import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function InteractiveCard() {
  const cardRef = useRef(null);
  const { elementX, elementY, isInBounds } = useMouseMove({
    element: cardRef,
    throttle: 16
  });
  
  // Calculate rotation based on mouse position
  const getRotation = () => {
    if (!isInBounds || !cardRef.current) return { rotateX: 0, rotateY: 0 };
    
    const { clientWidth, clientHeight } = cardRef.current;
    const centerX = clientWidth / 2;
    const centerY = clientHeight / 2;
    
    const rotateX = ((elementY - centerY) / centerY) * -10;
    const rotateY = ((elementX - centerX) / centerX) * 10;
    
    return { rotateX, rotateY };
  };
  
  const { rotateX, rotateY } = getRotation();
  
  return (
    <div style={{ padding: '50px', display: 'flex', justifyContent: 'center' }}>
      <div
        ref={cardRef}
        style={{
          width: '300px',
          height: '200px',
          backgroundColor: '#fff',
          borderRadius: '12px',
          boxShadow: '0 10px 30px rgba(0,0,0,0.2)',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          cursor: 'pointer',
          transform: `perspective(1000px) rotateX(\${rotateX}deg) rotateY(\${rotateY}deg) scale(\${isInBounds ? 1.05 : 1})`,
          transition: isInBounds ? 'none' : 'transform 0.3s ease-out',
        }}
      >
        <div style={{ textAlign: 'center' }}>
          <h3>Interactive Card</h3>
          <p>Hover to see 3D effect</p>
          {isInBounds && (
            <p style={{ fontSize: '12px', color: '#666' }}>
              Mouse: ({Math.round(elementX)}, {Math.round(elementY)})
            </p>
          )}
        </div>
      </div>
    </div>
  );
}

Cursor Follower

Create a custom cursor that follows the mouse:

import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function CursorFollower() {
  const { x, y } = useMouseMove({ throttle: 8 });
  
  return (
    <div style={{ height: '100vh', cursor: 'none' }}>
      <div style={{ padding: '20px' }}>
        <h2>Custom Cursor Follower</h2>
        <p>Move your mouse around to see the custom cursor</p>
        <button style={{ margin: '10px', padding: '10px 20px' }}>
          Hover me
        </button>
        <button style={{ margin: '10px', padding: '10px 20px' }}>
          And me
        </button>
      </div>
      
      {/* Custom cursor */}
      <div
        style={{
          position: 'fixed',
          left: x,
          top: y,
          width: '20px',
          height: '20px',
          backgroundColor: 'rgba(255, 0, 150, 0.8)',
          borderRadius: '50%',
          pointerEvents: 'none',
          zIndex: 9999,
          transform: 'translate(-50%, -50%)',
          transition: 'transform 0.1s ease-out',
        }}
      />
      
      {/* Cursor trail */}
      <div
        style={{
          position: 'fixed',
          left: x,
          top: y,
          width: '40px',
          height: '40px',
          border: '2px solid rgba(255, 0, 150, 0.3)',
          borderRadius: '50%',
          pointerEvents: 'none',
          zIndex: 9998,
          transform: 'translate(-50%, -50%)',
          transition: 'all 0.2s ease-out',
        }}
      />
    </div>
  );
}

Drawing Canvas

Use mouse tracking for drawing applications:

import { useRef, useState, useEffect } from 'react';
import { useMouseMove } from '@aniruddha1806/use-mouse-move';

function DrawingCanvas() {
  const canvasRef = useRef(null);
  const [isDrawing, setIsDrawing] = useState(false);
  const [lastPosition, setLastPosition] = useState({ x: 0, y: 0 });
  
  const { elementX, elementY, isInBounds } = useMouseMove({
    element: canvasRef,
    throttle: 8
  });
  
  // Handle drawing
  useEffect(() => {
    if (!isDrawing || !isInBounds || !canvasRef.current) return;
    
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    
    ctx.beginPath();
    ctx.moveTo(lastPosition.x, lastPosition.y);
    ctx.lineTo(elementX, elementY);
    ctx.stroke();
    
    setLastPosition({ x: elementX, y: elementY });
  }, [elementX, elementY, isDrawing, isInBounds, lastPosition]);
  
  const startDrawing = (e) => {
    setIsDrawing(true);
    setLastPosition({ x: elementX, y: elementY });
  };
  
  const stopDrawing = () => {
    setIsDrawing(false);
  };
  
  const clearCanvas = () => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  };
  
  return (
    <div style={{ padding: '20px' }}>
      <h2>Drawing Canvas</h2>
      <p>Click and drag to draw</p>
      
      <div style={{ marginBottom: '10px' }}>
        <button onClick={clearCanvas}>Clear Canvas</button>
      </div>
      
      <canvas
        ref={canvasRef}
        width={600}
        height={400}
        onMouseDown={startDrawing}
        onMouseUp={stopDrawing}
        onMouseLeave={stopDrawing}
        style={{
          border: '2px solid #333',
          cursor: 'crosshair',
          backgroundColor: 'white',
        }}
      />
      
      <p style={{ marginTop: '10px', fontSize: '14px', color: '#666' }}>
        Mouse: ({Math.round(elementX || 0)}, {Math.round(elementY || 0)}) | 
        Drawing: {isDrawing ? 'Yes' : 'No'}
      </p>
    </div>
  );
}

TypeScript Usage

The hook provides full TypeScript support:

import { useRef } from 'react';
import { useMouseMove } from '@aniruddha1806/use-mouse-move';

interface MousePosition {
  x: number;
  y: number;
  elementX: number | null;
  elementY: number | null;
  isInBounds: boolean;
}

interface UseMouseMoveOptions {
  element?: React.RefObject<HTMLElement> | null;
  throttle?: number;
  debounce?: number;
}

function TypedMouseTracker() {
  const elementRef = useRef<HTMLDivElement>(null);
  
  // Hook with typed options
  const options: UseMouseMoveOptions = {
    element: elementRef,
    throttle: 16,
    debounce: 0
  };
  
  // Destructure with proper typing
  const mouseData: MousePosition = useMouseMove(options);
  const { x, y, elementX, elementY, isInBounds } = mouseData;
  
  return (
    <div>
      <div ref={elementRef} style={{ width: 300, height: 200, border: '1px solid #ccc' }}>
        <p>Global: ({x}, {y})</p>
        <p>Element: ({elementX}, {elementY})</p>
        <p>In bounds: {isInBounds.toString()}</p>
      </div>
    </div>
  );
}

// Custom hook using useMouseMove
function useMouseDistance(elementRef: React.RefObject<HTMLElement>) {
  const { elementX, elementY, isInBounds } = useMouseMove({
    element: elementRef,
    throttle: 16
  });
  
  const distance = React.useMemo(() => {
    if (!isInBounds || elementX === null || elementY === null || !elementRef.current) {
      return 0;
    }
    
    const centerX = elementRef.current.clientWidth / 2;
    const centerY = elementRef.current.clientHeight / 2;
    
    return Math.sqrt(
      Math.pow(elementX - centerX, 2) + Math.pow(elementY - centerY, 2)
    );
  }, [elementX, elementY, isInBounds, elementRef]);
  
  return { distance, isInBounds };
}

Performance Tips

1. Use Throttling for Smooth Animations

For smooth 60fps animations, use a 16ms throttle:

const { x, y } = useMouseMove({ throttle: 16 });

2. Use Debouncing for Expensive Operations

For operations that don't need real-time updates:

const { x, y } = useMouseMove({ debounce: 100 });

3. Combine with useMemo for Complex Calculations

const { elementX, elementY } = useMouseMove({ element: ref });

const expensiveCalculation = useMemo(() => {
  // Expensive calculation based on mouse position
  return complexFunction(elementX, elementY);
}, [elementX, elementY]);