JSFiddle - React, Tailwind, and code Playground

by jcubed111

HTML

<canvas id='main' width=500 height=500></canvas>

CSS

body{
    margin: 0;
}

canvas{
    background: #000;
}

JavaScript

function rand(min, max) {
	return Math.random() * (max - min) + min;
}

function randColor(colors) {
	const i = Math.random() * (colors.length - 1);
    return colors[~~i].lerp(colors[~~i+1], Math.random());
}

let canvas = document.getElementById('main');
let ctx = canvas.getContext('2d');

let particles = [];

class Vec{
	constructor(x, y, z = 0, w = 1) {
    	this.x = x;
        this.y = y;
        this.z = z;
        this.w = w;
    }
    
    plus(b, factor = 1, wFactor = factor) {
    	return new this.constructor(this.x + b.x * factor, this.y + b.y * factor, this.z + b.z * factor, this.w + b.w * wFactor);
    }
    
    times(factor, wFactor = factor) {
    	return new this.constructor(this.x * factor, this.y * factor, this.z * factor, this.w * wFactor);
    }
    
    minus(b, factor = 1, wFactor = factor) {
    	return this.plus(b, -factor, -wFactor);
    }
    
    lerp(other, factor) {
    	return this.times(1 - factor).plus(other, factor);
    }
}
class Color extends Vec{
    atAlpha(a) {
    	return new Color(this.x, this.y, this.z, this.w * a);
    }
    
    toString() {
    	return `rgba(${~~this.x}, ${~~this.y}, ${~~this.z}, ${this.w})`;
    }
}

class Particle{
	constructor(pos, vel, color, life) {
    	this.pos = pos;
        this.vel = vel;
        this.color = color;
        this.life = life;
        this.maxLife = life;
    }
    
    render() {
    	const alpha = Math.pow(this.life / this.maxLife, 0.5);
    	ctx.fillStyle = this.color.atAlpha(alpha).toString();
    	ctx.fillRect(~~this.pos.x, ~~this.pos.y, 2, 2);
    }
    
    step(dt) {
    	this.pos = this.pos.plus(this.vel, dt);
        this.vel.y += 20000 * dt*dt;
        this.life -= dt;
    }
}

function makeParticles(pos, radius, colors) {
	for(let x = -radius; x < radius; x++) {
    	for(let y = -radius; y < radius; y++) {
        	if(x*x + y*y >= radius * radius) continue;
        	//if(x*x + y*y < 2) continue;
            let dp = new Vec(
            	x*rand(0.5, 1.5)+rand(-1,...