Daniel Petho

useMouseVector

Component 51

About

A custom React hook that tracks mouse/touch movement and calculates motion vectors. Provides both position coordinates and movement vectors relative to a container or the window.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds useMouseVector to your project and fits it to your theme.

Code

How useMouseVector is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

'use client'

import { useRef } from "react"
import { motion } from "framer-motion"
import { useMouseVector } from "@/components/hooks/use-mouse-vector"

function MouseVectorDemo() {
  const containerRef = useRef<HTMLDivElement>(null)
  const { position, vector } = useMouseVector(containerRef)

  // Calculate vector magnitude and angle
  const magnitude = Math.sqrt(vector.dx * vector.dx + vector.dy * vector.dy)
  const angle = (Math.atan2(vector.dy, vector.dx) * 180) / Math.PI

  // Scale the magnitude for visualization
  const scaledMagnitude = Math.min(magnitude * 2, 100)

  return (
    <div className="grid grid-cols-1 md:grid-cols-2 gap-8 p-8 max-w-4xl mx-auto">
      {/* Interactive Area */}
      <div className="space-y-4">
        <div className="space-y-2">
          <h3 className="text-lg font-medium">Mouse Vector Visualization</h3>
          <p className="text-sm text-muted-foreground">
            Move your cursor inside the box to see the vector
          </p>
        </div>
        <div 
          ref={containerRef}
          className="relative aspect-square w-full border rounded-lg bg-muted/30 overflow-hidden"
        >
          {/* Current Position Indicator */}
          <motion.div
            className="absolute w-4 h-4 bg-blue-500 rounded-full"
            style={{
              left: position.x - 8,
              top: position.y - 8,
            }}
          />
          
          {/* Vector Line */}
          <svg
            className="absolute inset-0 w-full h-full pointer-events-none"
            style={{ overflow: 'visible' }}
          >
            <motion.line
              x1={position.x}
              y1={position.y}
              x2={position.x + vector.dx * 5}
              y2={position.y + vector.dy * 5}
              stroke="#3b82f6"
              strokeWidth="2"
              initial={{ pathLength: 0 }}
              animate={{ pathLength: 1 }}
            />
          </svg>
        </div>
      </div>

      {/* Real-time Data Display */}
      <div className="space-y-4">
        <div className="space-y-2">
          <h3 className="text-lg font-medium">Vector Data</h3>
          <p className="text-sm text-muted-foreground">
            Real-time mouse movement metrics
          </p>
        </div>
        <div className="space-y-4 p-6 border rounded-lg bg-muted/30">
          <div className="grid grid-cols-2 gap-4">
            <div>
              <div className="text-sm font-medium mb-1">Position</div>
              <div className="font-mono text-sm">
                x: {Math.round(position.x)}<br />
                y: {Math.round(position.y)}
              </div>
            </div>
            <div>
              <div className="text-sm font-medium mb-1">Vector</div>
              <div className="font-mono text-sm">
                dx: {vector.dx.toFixed(2)}<br />
                dy: {vector.dy.toFixed(2)}
              </div>
            </div>
            <div>
              <div className="text-sm font-medium mb-1">Magnitude</div>
              <div className="font-mono text-sm">
                {magnitude.toFixed(2)}
              </div>
            </div>
            <div>
              <div className="text-sm font-medium mb-1">Angle</div>
              <div className="font-mono text-sm">
                {angle.toFixed(2)}°
              </div>
            </div>
          </div>

          {/* Magnitude Visualizer */}
          <div className="mt-4">
            <div className="text-sm font-medium mb-2">Velocity</div>
            <div className="h-2 bg-muted rounded-full overflow-hidden">
              <motion.div
                className="h-full bg-blue-500"
                animate={{ width: `${scaledMagnitude}%` }}
                transition={{ type: "spring", bounce: 0 }}
              />
            </div>
          </div>
        </div>
      </div>

      {/* Documentation */}
      <div className="md:col-span-2">
        <div className="space-y-4 p-6 border rounded-lg">
          <h3 className="text-lg font-medium">About useMouseVector</h3>
          <div className="space-y-4">
            <pre className="bg-muted p-4 rounded-md text-xs overflow-x-auto">
              {`const { position, vector } = useMouseVector(containerRef)

// position: { x: number, y: number }
// vector: { dx: number, dy: number }`}
            </pre>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
              <div>
                <h4 className="font-medium mb-2">Features</h4>
                <ul className="list-disc list-inside space-y-1 text-muted-foreground">
                  <li>Mouse position tracking</li>
                  <li>Movement vector calculation</li>
                  <li>Container-relative coordinates</li>
                  <li>Touch support</li>
                </ul>
              </div>
              <div>
                <h4 className="font-medium mb-2">Use Cases</h4>
                <ul className="list-disc list-inside space-y-1 text-muted-foreground">
                  <li>Particle effects</li>
                  <li>Cursor trails</li>
                  <li>Interactive animations</li>
                  <li>Gesture detection</li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export { MouseVectorDemo }

Dependencies

More by Daniel Petho

View all
  • Parallax Floating

    Parallax Floating

    2.2K
  • Text Rotate

    Text Rotate

    2.1K
  • Typewriter

    Typewriter

    1.9K
  • Marquee Along SVG Path

    Marquee Along SVG Path

    1.4K
  • Image Trail

    Image Trail

    1.4K
  • Animated Gradient With SVG

    Animated Gradient With SVG

    884
  • Text Cursor Proximity

    Text Cursor Proximity

    781
  • Pixel Trail

    Pixel Trail

    645