<canvas id=c></canvas>
canvas {
  
  position: absolute;
  top: 0;
  left: 0;
}
var w = c.width = window.innerWidth,
    h = c.height = window.innerHeight,
    ctx = c.getContext( '2d' ),
    
    opts = {
      
      spacing: 50,
      baseSize: 25,
      addedSize: 20,
      
      multX: 1,
      multY: 1,
      multSum: -.01,
      tickSpeed: .01,
      hueMult: 10,
    },
    
    tick = 0;

function loop() {
  
  window.requestAnimationFrame( loop );
  
  ctx.fillStyle = 'black';
  ctx.fillRect( 0, 0, w, h );
  
  tick += opts.tickSpeed;
  var addedHue = tick * opts.hueMult,
      limitX = c.width + opts.spacing,
      limitY = c.height + opts.spacing;
  
  for( var x = 0; x < limitX; x += opts.spacing ){
    
    var xTimesMult = x * opts.multX,
        hueX = x / limitX * 360 + tick * opts.hueMult;
    
    for( var y = 0; y < limitY; y += opts.spacing ){
      
      var size = opts.baseSize + opts.addedSize * Math.sin( ( xTimesMult + y * opts.multY ) * opts.multSum + tick );
      
      ctx.fillStyle = 'hsl(hue,80%,50%)'.replace( 'hue', hueX );
      ctx.fillRect( x - size / 2, y - size / 2, size, size );
    }
  }
}
loop();

// just handlers and gui related stuff

window.addEventListener( 'resize', function(){
  
  w = c.width = window.innerWidth;
  h = c.height = window.innerHeight;
});

gui = new dat.GUI;
gui.add( opts, 'spacing', 10, 100 );
gui.add( opts, 'baseSize', 0, 100 );
gui.add( opts, 'addedSize', 0, 100 );

gui.add( opts, 'multX', -1, 1 );
gui.add( opts, 'multY', -1, 1 );
gui.add( opts, 'multSum', -.2, .2 );
gui.add( opts, 'tickSpeed', 0, 1 );
gui.add( opts, 'hueMult', 0, 50 );

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js