ashish rajwani

ASMR backgroung with mouse hover effect

Component

About

a satisfying background

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

Code

How ASMR backgroung with mouse hover effect is used: the demo's code. The component's own source comes with a free account.

Usage.tsx


import React, { useEffect, useRef } from 'react';

/**
 * MesmerizingMercuryBackground
 * A refined interactive fluid-mesh background with clean, non-glittery visuals.
 * Optimized for organic movement and premium matte interactions.
 */

interface ParticleType {
  x: number;
  y: number;
  originX: number;
  originY: number;
  vx: number;
  vy: number;
  col: number;
  row: number;
  hue: number;
  size: number;
  friction: number;
  ease: number;
  noiseOffset: number;
}

const MesmerizingMercuryBackground: React.FC = () => {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const mouseRef = useRef({ 
    x: -2000, 
    y: -2000, 
    vx: 0, 
    vy: 0, 
    lastX: 0, 
    lastY: 0,
    active: false 
  });
  const particlesRef = useRef<ParticleType[]>([]);
  const animationRef = useRef<number>();

  // Configuration
  const ROWS = 32;
  const COLS = 50;
  const MOUSE_RADIUS = 320;
  const MOTION_BLUR = 0.18; // 0 to 1

  const init = (canvas: HTMLCanvasElement) => {
    const width = window.innerWidth;
    const height = window.innerHeight;
    canvas.width = width;
    canvas.height = height;

    const spacingX = width / (COLS - 1);
    const spacingY = height / (ROWS - 1);
    const newParticles: ParticleType[] = [];

    for (let i = 0; i < ROWS; i++) {
      for (let j = 0; j < COLS; j++) {
        newParticles.push({
          x: j * spacingX,
          y: i * spacingY,
          originX: j * spacingX,
          originY: i * spacingY,
          vx: 0,
          vy: 0,
          col: j,
          row: i,
          hue: 200 + (j / COLS) * 60,
          size: 0.8 + Math.random() * 1.5,
          friction: 0.89 + Math.random() * 0.03,
          ease: 0.025 + Math.random() * 0.02,
          noiseOffset: Math.random() * Math.PI * 2,
        });
      }
    }
    particlesRef.current = newParticles;
  };

  const drawLink = (
    ctx: CanvasRenderingContext2D, 
    p1: ParticleType, 
    p2: ParticleType, 
    limit: number
  ) => {
    const dx = p1.x - p2.x;
    const dy = p1.y - p2.y;
    const dist = Math.sqrt(dx * dx + dy * dy);

    if (dist < limit) {
      const alpha = (1 - dist / limit) * 0.3;
      ctx.strokeStyle = `hsla(${p1.hue}, 60%, 75%, ${alpha})`;
      ctx.lineWidth = 0.6;
      ctx.beginPath();
      ctx.moveTo(p1.x, p1.y);
      ctx.lineTo(p2.x, p2.y);
      ctx.stroke();
    }
  };

  const animate = (time: number) => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d', { alpha: false });
    if (!ctx) return;

    // Update mouse velocity
    const m = mouseRef.current;
    m.vx = (m.x - m.lastX) * 0.12;
    m.vy = (m.y - m.lastY) * 0.12;
    m.lastX = m.x;
    m.lastY = m.y;

    // Background trail for motion blur
    ctx.fillStyle = `rgba(3, 3, 10, ${MOTION_BLUR})`;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    const particles = particlesRef.current;
    const limit = (canvas.width / COLS) * 1.8;

    // 1. Update positions
    for (const p of particles) {
      // Harmonic breathing motion
      const waveX = Math.sin(time * 0.0008 + p.noiseOffset) * 12;
      const waveY = Math.cos(time * 0.001 + p.noiseOffset) * 12;
      
      const targetX = p.originX + waveX;
      const targetY = p.originY + waveY;

      // Mouse Physics
      const dx = m.x - p.x;
      const dy = m.y - p.y;
      const dist = Math.sqrt(dx * dx + dy * dy);

      if (dist < MOUSE_RADIUS) {
        const force = (1 - dist / MOUSE_RADIUS);
        const angle = Math.atan2(dy, dx);
        
        // Displacement (Push away)
        p.vx -= Math.cos(angle) * force * 0.6;
        p.vy -= Math.sin(angle) * force * 0.6;

        // Viscous Swirl (Drag)
        if (m.active) {
          const swirlIntensity = force * 3.5;
          p.vx += m.vx * swirlIntensity;
          p.vy += m.vy * swirlIntensity;
        }
      }

      // Return to origin (Spring)
      p.vx += (targetX - p.x) * p.ease;
      p.vy += (targetY - p.y) * p.ease;

      p.vx *= p.friction;
      p.vy *= p.friction;
      p.x += p.vx;
      p.y += p.vy;

      // Update color based on speed and position
      const velocity = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
      p.hue = 210 + (velocity * 15) + (p.col / COLS) * 40;
    }

    // 2. Draw Connections
    ctx.lineCap = 'round';
    for (let i = 0; i < particles.length; i++) {
      const p = particles[i];
      if (p.col < COLS - 1) drawLink(ctx, p, particles[i + 1], limit);
      if (p.row < ROWS - 1) drawLink(ctx, p, particles[i + COLS], limit);
    }

    // 3. Draw Nodes (Mercury Droplets) - REFINED: REMOVED GLITTER / SHADOWS
    ctx.shadowBlur = 0;
    ctx.shadowColor = 'transparent';
    
    for (const p of particles) {
      const vel = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
      
      // We use a solid but soft high-light fill without the shadowBlur glitter effect
      ctx.fillStyle = `hsla(${p.hue}, 80%, 85%, 0.85)`;
      
      ctx.beginPath();
      // Reduced scale on movement for a smoother, less "explosive" look
      ctx.arc(p.x, p.y, p.size + vel * 0.2, 0, Math.PI * 2);
      ctx.fill();
    }
    
    animationRef.current = requestAnimationFrame(animate);
  };

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    init(canvas);
    animationRef.current = requestAnimationFrame(animate);

    const handleMouseMove = (e: MouseEvent) => {
      mouseRef.current.x = e.clientX;
      mouseRef.current.y = e.clientY;
      mouseRef.current.active = true;
    };

    const handleTouchMove = (e: TouchEvent) => {
      if (e.touches.length > 0) {
        mouseRef.current.x = e.touches[0].clientX;
        mouseRef.current.y = e.touches[0].clientY;
        mouseRef.current.active = true;
      }
    };

    const handleResize = () => {
      if (canvas) init(canvas);
    };

    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('touchmove', handleTouchMove);
    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('touchmove', handleTouchMove);
      window.removeEventListener('resize', handleResize);
      if (animationRef.current) cancelAnimationFrame(animationRef.current);
    };
  }, []);

  return (
    <div className="fixed inset-0 w-full h-full overflow-hidden bg-[#03030a] -z-10">
      <canvas
        ref={canvasRef}
        className="block w-full h-full pointer-events-none"
      />
      {/* Cinematic Overlays */}
      <div className="absolute inset-0 pointer-events-none bg-[radial-gradient(circle_at_center,transparent_0%,rgba(0,0,0,0.5)_100%)]" />
      <div 
        className="absolute inset-0 pointer-events-none opacity-[0.03]" 
        style={{ backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")` }}
      />
    </div>
  );
};

export default MesmerizingMercuryBackground;
/**
 * REFINEMENT NOTES:
 * 1. REMOVED GLITTER: Removed ctx.shadowBlur and ctx.shadowColor logic from the drawing loop to eliminate the sparkly glitter effect on hover.
 * 2. MATTE FINISH: Adjusted the particle opacity and fill style for a cleaner, more fluid mercury look.
 * 3. SUBTLE PHYSICS: Reduced the velocity-based size scaling to keep the visual density consistent even during fast mouse movements.
 */

More by ashish rajwani

View all
  • ASMR background

    ASMR background

    685
  • animated pattern cloud

    animated pattern cloud

    616
  • Balloons Pop background

    Balloons Pop background

    362
  • realistic fog background

    realistic fog background

    309
  • 3d animated stars background

    3d animated stars background

    3
  • Matrix background

    Matrix background

    1
  • tab pages

    tab pages

    1
  • sleek text input

    sleek text input