JSFiddle - React, Tailwind, and code Playground

HTML

<canvas id="canvas"></canvas>

CSS

* {
  margin: 0;
  padding: 0;
}

JavaScript

const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
const W = canvas.width = window.innerWidth;
const H = canvas.height = window.innerHeight;
const balls = [];
const ballsNum = 250;
const fl = 250;
const vpX = W / 2;
const vpY = H / 2;
let mouseX = 0;
let mouseY = 0;
let angleX;
let angleY;

class Ball {
  constructor(radius=40, color='#fff') {
    this.x = 0;
    this.y = 0;
    this.xpos = 0;
    this.ypos = 0;
    this.zpos = 0;
    this.vx = 0;
    this.vy = 0;
    this.vz = 0;
    this.radius = radius;
    this.rotation = 0;
    this.mass = 1;
    this.scaleX = 1;
    this.scaleY = 1;
    this.color = color;
    this.visible = true;
  }

  draw(ctx) {
    ctx.save();
    ctx.translate(this.x, this.y);
    // ctx.rotate(this.rotation);
    ctx.scale(this.scaleX, this.scaleY);
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(0, 0, this.radius, 0, (Math.PI / 180) * 360, false);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
  }
}

function move(ball) {
  rotateX(ball, angleX);
  rotateY(ball, angleY);
  setPerspective(ball);
}

function rotateX(ball, angle) {
  const cos = Math.cos(angle);
  const sin = Math.sin(angle);
  const y1 = ball.ypos * cos - ball.zpos * sin;
  const z1 = ball.zpos * cos + ball.ypos * sin;
  ball.ypos = y1;
  ball.zpos = z1;
}

function rotateY(ball, angle) {
  const cos = Math.cos(angle);
  const sin = Math.sin(angle);
  const x1 = ball.xpos * cos - ball.zpos * sin;
  const z1 = ball.zpos * cos + ball.xpos * sin;
  ball.xpos = x1;
  ball.zpos = z1;
}

function setPerspective(ball) {
  if (ball.zpos > -fl) {
    ball.scaleX = ball.scaleY = fl / (fl + ball.zpos);
    ball.x = vpX + ball.xpos * ball.scaleX;
    ball.y = vpY + ball.ypos * ball.scaleY;
    ball.visible = true;
  } else {
    ball.visible = false;
  }
}

function zSort(a, b) {
  return b.zpos - a.zpos;
}

function draw(ball) {
  if (ball.visible) {
    ball.draw(ctx);
  }
}

function mouseMove(e) {
  mouseX =...