<canvas id="canvas-bg"></canvas>
    <canvas id="canvas"></canvas>
    <div class="header">
        <div class="icon green" id="green">
            <i></i>
        </div>
        <div class="icon blue" id="blue">
            <i></i>
        </div>
        <div class="icon biege" id="biege">
            <i></i>
        </div>
    </div>
    <footer>
      <span>
        <p>@weirdyang</p>
      </span>
    </footer>
    <svg>
      <defs>
        <filter id="goo">
          <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
          <feColorMatrix
            in="blur"
            type="matrix"
            values="1 0 0 0 0
                        0 1 0 0 0
                        0 0 1 0 0
                        0 0 0 30 -25"
            result="goo"
          />
          <feBlend in="SourceGraphic" in2="goo" />
        </filter>
      </defs>
    </svg>
* {
  box-sizing: border-box;
}
body {
  background-color: #164a41;
  transition: background-color 1000ms linear;
}
canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  filter: url('#goo');
}
footer {
  position: absolute;
  height: 50px;
  left: 0;
  bottom: 0;
  width: 100%;
  text-align: right;
  padding: 10px;
  font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;;
}
.header {
  height: 50px;
  width: 100%;
  left: 0;
  position: absolute;
  top: 0;
  padding: 40px;
  display: flex;
}
/* <!--https://codepen.io/raulghm/pen/EjdwoO--!> */
@-webkit-keyframes anim-glow {
  0% {
    box-shadow: 0 0 grey;
  }
  100% {
    box-shadow: 0 0 10px 8px transparent;
    border-width: 2px;
  }
}
@keyframes anim-glow {
  0% {
    box-shadow: 0 0 grey;
  }
  100% {
    box-shadow: 0 0 10px 8px transparent;
    border-width: 1px;
  }
}
.icon {
  border-radius: 50%;
  border: 2px solid #61ef61;
  width: 10px;
  height: 10px;
  text-align: center;
  position: relative;
  -webkit-animation: anim-glow 2s ease infinite;
  animation: anim-glow 2s ease infinite;
  margin-right: 1em;
}
.icon i {
  border-radius: 50%;
  display: inline-block;
  vertical-align: 8px;
  line-height: 1;
  transform: 0.2em;
}

.icon.blue {
  border: 2px solid #007cc7;
}
.icon.blue i {
  border: 2px solid #007cc7;
  background-color: #007cc7;
}
.icon.biege {
  border: 2px solid #4F4846;
}
.icon.biege i {
  border: 2px solid #4F4846;
  background-color: #4F4846;
}
.icon.green {
  border: 2px solid #61ef61;
}
.icon.green i {
  border: 2px solid #61ef61;
  background-color: #61ef61;
}

.icon.green {
  border: 2px solid #61ef61;
}
.icon.green i {
  border: 2px solid #61ef61;
  background-color: #61ef61;
}
// color
// back is lightest
// body is darkest
const green = {
  front: '#4D774E',
  back: '#9DC88D',
  body: '#164a41',
};
const blue = {
  front: '#203647',
  back: '#4DA8DA',
  body: '#12232E',
};
const biege = {
  front: '#E8CEBF',
  back: '#FDF8F5',
  body: '#DDAF94'
}
const colorPicker = {
  green: green,
  blue: blue,
  biege: biege,
};
// canvas 1
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const front = {
  canvas: document.getElementById('canvas'),
  context: canvas.getContext('2d'),
  bubbles: [],
  color: '#4D774E',
  sizeFactor: 4,
  speed: 3,
};
// canvas 2
const canvasBg = document.getElementById('canvas-bg');
const ctxBg = canvasBg.getContext('2d');
canvasBg.width = window.innerWidth;
canvasBg.height = window.innerHeight;
const back = {
  canvas: document.getElementById('canvas-bg'),
  context: canvasBg.getContext('2d'),
  bubbles: [],
  color: '#9DC88D',
  sizeFactor: 12,
  speed: 5,
};
// bubbles
function pushBubble(array, color, speed) {
  array.push(new Bubble(color, speed));
}

function reset(canvasObject) {
  canvasObject.canvas.width = window.innerWidth;
  canvasObject.canvas.height = window.innerHeight;
  canvasObject.bubbles = [];
}

class Bubble {
  constructor(color, yVelocity) {
    this.radius = Math.random() * 150 + 30;
    this.life = true;
    this.xPos = Math.random() * window.innerWidth;
    this.yPos = Math.random() * 20 + window.innerHeight + this.radius;
    this.vy = Math.random() * 0.0002 + 0.001 + yVelocity;
    // speed of bubble shrinkage
    this.vr = 0;
    // -ve got left
    // +ve go right
    this.vx = Math.random() * 4 - 2;
    this.color = color;
  }
}
Bubble.prototype.draw = function(currentCtx){
    // console.log(currentCtx);
    currentCtx.beginPath();
    currentCtx.arc(this.xPos, this.yPos, this.radius, 0, 2 * Math.PI);
    currentCtx.fillStyle = this.color;
    currentCtx.fill();
}

Bubble.prototype.update = function() {
    // move upwards
    this.vy += 0.00001;
    // increase speed of shrinkage
    this.vr += 0.02;
    this.yPos -= this.vy;
    this.xPos += this.vx;
    if (this.radius > 1) {
      this.radius -= this.vr;
    }
    if (this.radius <= 1) {
      // onsole.log('hello');
      this.life = false;
      // kill bubble
    }
  }
function updateBubbles(array, sizeFactor, cb) {
  for (let i = array.length - 1; i >= 0; i--) {
    array[i].update();
    if (array[i].life === false) {
      // start - start of position to make change
      // delete - 1 from the index we passed in
      array.splice(i, 1);
    }
  }
  if (array.length < window.innerWidth / sizeFactor) {
    cb();
  }
}

function animate(current, array, sizeFactor, cb) {
  // console.log(current, array, sizeFactor,cb)
  current.clearRect(0, 0, canvas.width, canvas.height);

  updateBubbles(array, sizeFactor, cb);
  // console.log(current, array, sizeFactor, cb)
  for (let i = array.length - 1; i >= 0; i--) {
    array[i].draw(current);
  }
  requestAnimationFrame(() => {
    // console.log(current, array, sizeFactor, cb);
    animate(current, array, sizeFactor, cb);
  });
}

function animateObject(canvasObject) {
  animate(
    canvasObject.context,
    canvasObject.bubbles,
    canvasObject.sizeFactor,
    () => {
      pushBubble(canvasObject.bubbles, canvasObject.color, canvasObject.speed);
    },
  );
}
function startAnimate() {
  console.log('starting...');
  animateObject(front);
  animateObject(back);
}

function setUpColors() {
  const icons = document.querySelectorAll('.icon');
  console.log(icons);
  console.log(`setting up colors`);
  icons.forEach((element) => {
    element.addEventListener('click', (e) => {
      // alert(`${element.id}`);
      e.preventDefault();
      front.color = colorPicker[element.id].front;
      back.color = colorPicker[element.id].back;
      document.body.style.backgroundColor = colorPicker[element.id].body;
    });
  });
}
window.addEventListener('load', () =>{
  startAnimate();
  setUpColors();
});
window.addEventListener('resize', () => {
  reset(front);
  reset(back);
  startAnimate();
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.