Vertical Bars Noise

A canvas-based reactive background with noise-driven horizontal bars that animate, scatter, and ripple in response to mouse movement and clicks.

Generated using Grepped's AI UI component generator — created from scratch, not pulled from a library.

canvasnoisebarsinteractivebackgroundreactive

Live Preview — customize or regenerate this in the workspace

Loading preview…

Design Intent

Noise-driven bars arranged in horizontal rows that scatter and ripple with mouse interaction.

CSS

css
* { margin: 0; padding: 0; box-sizing: border-box; }
    html, body { width: 100%; height: 100%; overflow: hidden; background: #F0EEE6; }
    canvas { display: block; width: 100%; height: 100%; }

HTML

html
<canvas id="c"></canvas>

Full Source

html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    html, body { width: 100%; height: 100%; overflow: hidden; background: #F0EEE6; }
    canvas { display: block; width: 100%; height: 100%; }
  </style>
</head>
<body>
  <canvas id="c"></canvas>
  <script>
    var BG = '#F0EEE6';
    var LC = '#444444';
    var BC = '#000000';
    var LW = 1;
    var SPEED = 0.0005;
    var REMOVE_WAVE = true;

    function hexRgb(h) {
      var c = h.charAt(0) === '#' ? h.slice(1) : h;
      return { r: parseInt(c.slice(0,2),16), g: parseInt(c.slice(2,4),16), b: parseInt(c.slice(4,6),16) };
    }

    var canvas = document.getElementById('c');
    var time = 0;
    var mouse = { x: 0, y: 0, down: false };
    var ripples = [];

    function resize() {
      var dpr = window.devicePixelRatio || 1;
      canvas.width = innerWidth * dpr;
      canvas.height = innerHeight * dpr;
      canvas.style.width = innerWidth + 'px';
      canvas.style.height = innerHeight + 'px';
      canvas.getContext('2d').scale(dpr, dpr);
    }

    function noise(x, y, t) {
      var n = Math.sin(x*0.01+t)*Math.cos(y*0.01+t) + Math.sin(x*0.015-t)*Math.cos(y*0.005+t);
      return (n+1)/2;
    }

    function mouseFx(x, y) {
      var d = Math.sqrt((x-mouse.x)*(x-mouse.x)+(y-mouse.y)*(y-mouse.y));
      return Math.max(0, 1-d/200);
    }

    function rippleFx(x, y, now) {
      var tot = 0;
      for (var k=0; k<ripples.length; k++) {
        var r = ripples[k];
        var age = now - r.t;
        if (age < 2000) {
          var dx = x-r.x, dy = y-r.y;
          var dist = Math.sqrt(dx*dx+dy*dy);
          var rad = age/2000*300, w = 50;
          if (Math.abs(dist-rad) < w) tot += (1-age/2000)*r.i*(1-Math.abs(dist-rad)/w);
        }
      }
      return Math.min(tot, 2);
    }

    function draw() {
      var ctx = canvas.getContext('2d');
      time += SPEED;
      var now = Date.now();
      var W = canvas.clientWidth, H = canvas.clientHeight;
      var nLines = Math.floor(H/11);
      var sp = H/nLines;
      var lc = hexRgb(LC), bc = hexRgb(BC);

      ctx.fillStyle = BG;
      ctx.fillRect(0, 0, W, H);

      for (var i=0; i<nLines; i++) {
        var y = i*sp + sp/2;
        var mfy = mouseFx(W/2, y);
        var alpha = Math.max(0.3, 0.3+mfy*0.7);
        ctx.beginPath();
        ctx.strokeStyle = 'rgba('+lc.r+','+lc.g+','+lc.b+','+alpha+')';
        ctx.lineWidth = LW + mfy*2;
        ctx.moveTo(0, y); ctx.lineTo(W, y); ctx.stroke();

        for (var x=0; x<W; x+=8) {
          var nv = noise(x, y, time);
          var mf = mouseFx(x, y);
          var rf = rippleFx(x, y, now);
          var inf = mf+rf;
          var thr = Math.max(0.2, 0.5-mf*0.2-Math.abs(rf)*0.1);
          if (nv > thr) {
            var bw = 3+nv*10+inf*5;
            var bh = 2+nv*3+inf*3;
            var ax = x + Math.sin(time+y*0.0375)*20*nv
              + (mouse.down ? Math.sin(time*3+x*0.01)*10*mf : 0)
              + rf*Math.sin(time*2+x*0.02)*15;
            var inten = Math.min(1, Math.max(0.7, 0.7+inf*0.3));
            ctx.fillStyle = 'rgba('+bc.r+','+bc.g+','+bc.b+','+inten+')';
            ctx.fillRect(ax-bw/2, y-bh/2, bw, bh);
          }
        }
      }

      if (!REMOVE_WAVE) {
        var now2 = Date.now();
        for (var k=0; k<ripples.length; k++) {
          var r2 = ripples[k];
          var age2 = now2 - r2.t;
          if (age2 < 2000) {
            var p2 = age2/2000;
            ctx.beginPath();
            ctx.strokeStyle = 'rgba(100,100,100,'+(1-p2)*0.3*r2.i+')';
            ctx.lineWidth = 2;
            ctx.arc(r2.x, r2.y, p2*300, 0, Math.PI*2);
            ctx.stroke();
          }
        }
      }

      requestAnimationFrame(draw);
    }

    resize();
    window.addEventListener('resize', resize);
    canvas.addEventListener('mousemove', function(e) {
      var rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX-rect.left; mouse.y = e.clientY-rect.top;
    });
    canvas.addEventListener('mousedown', function(e) {
      mouse.down = true;
      var rect = canvas.getBoundingClientRect();
      ripples.push({ x: e.clientX-rect.left, y: e.clientY-rect.top, t: Date.now(), i: 1.5 });
      var now = Date.now();
      ripples = ripples.filter(function(r){ return now-r.t < 2000; });
    });
    canvas.addEventListener('mouseup', function(){ mouse.down = false; });
    draw();
  </script>
</body>
</html>

More Reactive Backgrounds Animations