<div>
      <button>1</button>
      <button>2</button>
      <button>3</button>
      <button>4</button>
      <button>5</button>
      <button>6</button>
      <button>7</button>
      <button>8</button>
      <button>9</button>
      <button>0</button>
      <button>Backspace</button>
    </div>
    <div>
      <button style="padding: 1rem 3rem;">Tab</button>
      <button>Q</button>
      <button>W</button>
      <button>E</button>
      <button>R</button>
      <button>T</button>
      <button>Y</button>
      <button>U</button>
      <button>I</button>
      <button>O</button>
      <button>P</button>
    </div>
    <div>
      <button>A</button>
      <button>S</button>
      <button>D</button>
      <button>F</button>
      <button>G</button>
      <button>H</button>
      <button>J</button>
      <button>K</button>
      <button>L</button>
      <button style="padding: 1rem 3rem;">Enter</button>
    </div>
    <div>
      <button style="padding: 1rem 3rem;">Shift</button>
      <button>Z</button>
      <button>X</button>
      <button>C</button>
      <button>V</button>
      <button>B</button>
      <button>N</button>
      <button>M</button>
    </div>
*
    margin: 0
    padding: 0
    box-sizing: border-box

canvas
    position: fixed
    top: 0
    left: 0
    z-index: -1

body
    min-width: 100vw
    min-height: 100vh
    display: flex
    justify-content: space-around
    align-items: center
    flex-direction: column
    background-color: #EFEEEE
    padding: 25vh 0

    div
        width: 100%
        display: flex
        justify-content: space-around
        padding: 0 10vw

button
    cursor: pointer
    padding: 1rem 2rem
    font-size: 2vmax
    font-family: Helvetica
    border: none
    background-color: #EFEEEE
    border-radius: 12px
    border: 2px solid rgba(255,255,255,.2)
    box-shadow: -6px -6px 26px 0 rgba(255,255,255,.83), 6px 6px 16px 0 rgba(217,210,200,0.51)
    transition: color 0.2s ease-out
    animation: button-focus-out 0.2s ease-out forwards
    color: dimgray
    user-select: none

    &:focus
        outline: none

    &.pressed
        color: orangered
        animation: button-focus 0.2s ease-out forwards
        outline: none

@keyframes button-focus
    0%
        box-shadow: -6px -6px 26px 0 rgba(255,255,255,.83), 6px 6px 16px 0 rgba(217,210,200,0.51)
    50%
        box-shadow: none
    100%
        box-shadow: -6px -6px 16px 0 rgba(255,255,255,.83) inset, 6px 6px 6px 0 rgba(217,210,200,0.51) inset

@keyframes button-focus-out
    0%
        box-shadow: -6px -6px 16px 0 rgba(255,255,255,.83) inset, 6px 6px 6px 0 rgba(217,210,200,0.51) inset
    50%
        box-shadow: none
    100%
        box-shadow: -6px -6px 26px 0 rgba(255,255,255,.83), 6px 6px 16px 0 rgba(217,210,200,0.51)
View Compiled
let balls = [];
let keyIsCurrentlyDown = false;
let somethingExploded = false;

window.addEventListener("keydown", event => {
  if (!keyIsCurrentlyDown) {
    keyIsCurrentlyDown = true;
    var audio = new Audio("./buttonclick.mp3");
    audio.play();
    for (var i = 0; i < $("button").length; i++) {
      let k = event.key;
      if (k.length < 2) k = k.toUpperCase();
      if (
        $("button")
          .eq(i)
          .html() === k
      ) {
        let chosenColor = color(random(255), random(255), random(255));

        let pos = $("button")
          .eq(i)
          .position();
        let size = {
          w: $("button")
            .eq(i)
            .outerWidth(),
          h: $("button")
            .eq(i)
            .outerHeight()
        };

        for (var j = 0; j < 5; j++) {
          balls.push(
            new Ball(pos.left + size.w / 2, pos.top + size.h / 2, chosenColor)
          );
        }

        $("button")
          .eq(i)
          .addClass("pressed")
          .css(
            "color",
            "rgb(" +
              chosenColor.levels[0] +
              "," +
              chosenColor.levels[1] +
              "," +
              chosenColor.levels[2] +
              ")"
          );
      }
    }
  }
});

window.addEventListener("keyup", event => {
  $("button")
    .removeClass("pressed")
    .css("color", "");
  keyIsCurrentlyDown = false;
});

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(239, 238, 238);
}

function draw() {
  if (somethingExploded) {
    background(239, 238, 238, 50);
  } else {
    background(239, 238, 238, 255);
  }

  //   if (frameCount % 1 == 0) {
  //     balls.push(new Ball(mouseX, mouseY));
  //   }

  for (var i = balls.length - 1; i >= 0; i--) {
    balls[i].draw();
    balls[i].update();
    if (balls[i].remove) {
      balls.splice(i, 1);
    }
  }
}

class Ball {
  constructor(x, y, clr) {
    this.pos = createVector(x, y);
    this.acc = createVector();
    this.vel = p5.Vector.fromAngle(random(TWO_PI));
    this.vel.setMag(random(3, 10));
    this.color = clr;
    this.size = random(5, 10);
    this.opacity = 255;
    this.remove = false;
    this.imploding = false;
  }
  draw() {
    fill(
      this.color.levels[0],
      this.color.levels[1],
      this.color.levels[2],
      this.opacity
    );
    noStroke();
    ellipse(this.pos.x, this.pos.y, this.size);
  }
  update() {
    this.vel.add(this.acc);
    this.vel.limit(20);
    this.pos.add(this.vel);
    this.acc.set(0, 0);

    if (this.pos.x >= width - this.size / 2 || this.pos.x <= 0 + this.size / 2)
      this.vel.x *= -1;
    if (this.pos.y >= height - this.size / 2 || this.pos.y <= 0 + this.size / 2)
      this.vel.y *= -1;

    this.pos.x = constrain(this.pos.x, this.size / 2, width - this.size / 2);
    this.pos.y = constrain(this.pos.y, this.size / 2, height - this.size / 2);

    if (mouseIsPressed) {
      let desired = p5.Vector.sub(createVector(mouseX, mouseY), this.pos);
      desired.setMag(5);
      let steer = desired.sub(this.acc);
      steer.setMag(5);
      this.acc.add(steer);
    }

    for (var i = 0; i < balls.length; i++) {
      if (balls[i] !== this && balls[i].color !== this.color) {
        if (!mouseIsPressed) {
          let desired = p5.Vector.sub(balls[i].pos, this.pos);
          desired.setMag(5);
          let steer = desired.sub(this.acc);
          steer.setMag(5 / (balls.length - 1));
          this.acc.add(steer);
        }
      } else if (balls[i] !== this) {
        let d = this.pos.dist(balls[i].pos);
        if (d < this.size / 2 + balls[i].size / 2) {
          let repulse = p5.Vector.sub(this.pos, balls[i].pos);
          repulse.setMag(5);
          this.acc.add(repulse);
        }
      }
    }

    for (var i = 0; i < balls.length; i++) {
      if (balls[i] !== this && balls[i].color !== this.color) {
        let d = balls[i].pos.dist(this.pos);
        if (
          d < this.size / 2 + balls[i].size / 2 &&
          this.size > balls[i].size
        ) {
          balls[i].remove = true;
          this.size += balls[i].size / 2;
        }
      }
    }

    if (this.size >= 500 && !this.imploding) {
      this.imploding = true;
    }

    if (this.imploding) {
      this.size -= 100;
      if (this.size <= 0) {
        somethingExploded = true;
        setTimeout(() => {
          somethingExploded = false;
        }, 1000);
        for (var i = 0; i < 50; i++) {
          let b = new Ball(this.pos.x, this.pos.y, this.color);
          b.size = 10;
          balls.push(b);
        }
        this.remove = true;
      }
    }
  }
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.min.js