<div id="options">
  <p>From: <span id="randFrom"></span></p>
  <p>Easing: <span id="randEasing"></span>
</div>

<a id="staakLogo" class="link" href="https://www.staak.co.uk/?ref=codepen&id=XowdeE" target="_blank" rel="noreferrer noopener">
  <svg class="link" xmlns="http://www.w3.org/2000/svg" viewBox="17 348.4 630.7 145.5">
    <path class="link" d="M255.4 450.9c-2.1 6.7-2.9 12.1-2.9 16.4 0 15.2 15 22.7 26 22.7v1.2h-59.9l.1-1.3c9.6 0 17.3-8.5 24-22.6l28.5-59.9.6 1.9c-7.1 15.4-12.3 27.9-15.4 37.8M381 490v1.2h-75V490c9.6 0 18.1-6.2 12.9-17l-39.3-82.7 19-42.5h2.1l61.5 131.4c3.8 8.1 8.6 10.8 18.8 10.8z"
          />
    <path class="link" d="M386 450.2c-2.1 6.7-2.9 12.1-2.9 16.4 0 15.2 15 22.7 26 22.7v1.2h-59.9v-.8c9.6 0 17.5-8.9 24.1-23.1l28.5-59.9.6 1.9c-7.1 15.4-12.3 27.9-15.4 37.8M511.1 490v1.2h-75V490c9.6 0 18.1-6.2 12.9-17l-39.3-82.7 19.1-42.5h2.1l61.5 131.4c3.7 8.1 8.5 10.8 18.7 10.8z"
          />
    <path class="link" d="M559.7 490v1.2h-66.3V490c12.5 0 15.6-5 15.6-10.6V362c0-5.6-3.1-10.8-15.6-10.8v-1.3h66.3v1.2c-12.3 0-15.4 5.2-15.4 10.8v117.5c0 5.6 3.2 10.6 15.4 10.6zm88.4 0v1.2h-68.2V490c6.4 0 11-3.1 11-7.3 0-4.4-1.2-6.7-2.9-9.1l-32.6-49.9c32.2-32.4 38.3-51.6 38.3-60.9 0-8.1-8.1-11.6-13.9-11.6v-1.3h61.1v1.2c-8.9 0-13.9 4.2-20.4 10.4L580.2 400l52.2 79.6c4 6.3 8 10.4 15.7 10.4zM19.1 442.6h-1.7v50.7h1.7l6.9-10.2c10.8 6.7 23.9 9.8 40.3 10.2v-1.2c-25.6-8.6-40.4-26-47.2-49.5zM48 368.2c0-11.4 8.7-17.5 18.3-19.1v-1.3C38.6 349.7 18.4 364 18.4 389c0 42.2 79.4 45.5 79.4 81.9 0 12.5-11.2 19.1-22.7 21.2v1.2c32.2-1.2 52.2-15.8 52.2-42.6.1-42.2-79.3-46.1-79.3-82.5zM204.9 479V349.9h-35.3V479c0 5.6-3.1 11-15.6 11v1.2h66.5V490c-12.5 0-15.6-5.4-15.6-11zM215.3 349.9v1.2c16 4 28.5 22.5 33.7 44.9h1.7v-46.1h-35.4zM159.2 349.9h-39.1l-7.5 8.9c-9.6-6.8-21.8-10.4-37.4-11v1.2c21.3 4.3 45.1 29.5 47.2 55.8l.2 4.1c6.2-34.7 20.2-53 36.6-57.8v-1.2z"
          /></svg>
</a>
body, html {
  margin: 0;
  padding: 0;
  display: flex;
  font-family: arial;
}

#options {
  width: 300px;
  position: absolute;
  top: 0px;
  left: 20px;
  color: #fff;
  text-align: left;
}

h1 {
  font-size: 26px;
}

p {
  font-size: 18px;
  line-height: 14px;
}

span {
  border-bottom: 1px dotted #fff;
}

#staakLogo {
  width: 4vw;
  max-width: 100px;
  min-width: 80px;
  position: absolute;
  bottom: 10px;
  left: 10px;
  z-index: 20;
  padding: 10px;
}

#staakLogo svg {
  width: 100%;
  display: block;
}
#staakLogo svg path {
  fill: #ffffff;
  -webkit-transition: fill 0.25s ease-in-out;
  transition: fill 0.25s ease-in-out;
}
class App {
  
  constructor() {
    
    this.randFrom = [
      'first',
      'last',
      'center'
    ];
    
    this.easing = [
      'linear',
      'easeInOutQuad',
      'easeInOutCubic',
      'easeInOutQuart',
      'easeInOutQuint',
      'easeInOutSine',
      'easeInOutExpo',
      'easeInOutCirc',
      'easeInOutBack',
      'cubicBezier(.5, .05, .1, .3)',
      'spring(1, 80, 10, 0)',
      'steps(10)'
    ];
    
    this.randFromText = document.getElementById('randFrom');
    this.randEasingText = document.getElementById('randEasing'); 
  }

  init() {

      this.camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 0.1, 1000 );
      this.camera.position.x = -45;
      this.camera.position.y = 30;
      this.camera.position.z = -45;
    
      // this.controls = new THREE.OrbitControls(this.camera);
      this.camera.lookAt(new THREE.Vector3(5,-5,5));

      this.scene = new THREE.Scene();
    
      this.resizeListener = e => this.onResize(e);
	    window.addEventListener( 'resize', this.resizeListener, false );
    
      this.createBoxes();

      this.renderer = new THREE.WebGLRenderer({
        antialias: true
      });

      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setSize( window.innerWidth, window.innerHeight );

      document.body.appendChild( this.renderer.domElement );
    
      this.beginAnimationLoop();

      this.animate();
  }
  
  createBoxes() {
    this.geometry = new THREE.BoxBufferGeometry(1, 10, 1);
    
    let vertexShader = `
      varying vec2 vUv;
      void main()	{
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
      }
    `;
    
    let fragmentShader = `
      #extension GL_OES_standard_derivatives : enable

      varying vec2 vUv;
      uniform float thickness;

      float edgeFactor(vec2 p){
        vec2 grid = abs(fract(p - 0.5) - 0.5) / fwidth(p) / thickness;
        return min(grid.x, grid.y);
      }

      void main() {

        float a = edgeFactor(vUv);

        vec3 c = mix(vec3(1), vec3(0), a);

        gl_FragColor = vec4(c, 1.0);
      }
    `;
    
    let material = new THREE.ShaderMaterial({
      uniforms: {
        thickness: {
          value: 1.5
        }
      },
      vertexShader,
      fragmentShader
    });
    
    let cube = new THREE.Mesh( this.geometry, material );      
    
    let offset = 1.25;
    this.nRows = 25;
    this.nCols = 25;
    this.staggerArray = [];
    
    for(var column = 0; column < this.nCols; column++) {
      for(var row = 0; row < this.nRows; row++) {
        let obj = cube.clone();
        obj.position.x = (row * offset) - ((this.nRows*0.5) + (this.geometry.parameters.width*0.5));
        obj.position.y = -(this.geometry.parameters.height*0.5);
        obj.position.z = (column * offset) - ((this.nCols*0.5) + (this.geometry.parameters.width*0.5));
        this.staggerArray.push(obj.position);
        this.scene.add(obj);
      }
    }
  }
  
  beginAnimationLoop() {
     
    // random from array
    let randFrom = this.randFrom[Math.floor(Math.random()*this.randFrom.length)];
    let easingString = this.easing[Math.floor(Math.random()*this.easing.length)];
    
    this.randFromText.textContent = randFrom;
    this.randEasingText.textContent = easingString;
    
    anime({
      targets: this.staggerArray,
      y: [
        {value: (this.geometry.parameters.height*0.25), duration: 500},
        {value: -(this.geometry.parameters.height*0.25), duration: 2000},
      ],
      delay: anime.stagger(200, {grid: [this.nRows, this.nCols], from: randFrom}),
      easing: easingString,
      complete: (anim) => this.beginAnimationLoop()
    });
    
  }

  animate() {

      requestAnimationFrame( () => this.animate() );
      this.update();
      this.render();
  }

  update() {
     
    // update orbit controls
    if(this.controls) {
      this.controls.update();
    }
  }

  render() {
    this.renderer.render( this.scene, this.camera );
  }
  
  onResize() {

    // scene & camera update
    this.camera.aspect = window.innerWidth / window.innerHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize( window.innerWidth, window.innerHeight );
  }
  
}

let app = new App();
app.init();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://threejs.org/build/three.min.js
  2. https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
  3. https://cdn.jsdelivr.net/npm/animejs@3.0.0/lib/anime.min.js