JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id='c' style="width:384px;height:216px" width="1920" height="1080"></canvas>
JavaScript
const c = document.getElementById('c')
const x = c.getContext('2d');
function random(seed) {
var x = Math.sin(seed) * 10000;
return x - Math.floor(x);
}
const rate = 2;
const lifespan = 1000
const particles = lifespan/rate;
const v_scale = 0.5;
const g = -0.001;
const base = 100;
const size = 80;
function S(x) {return Math.sin(x);}
function C(x) {return Math.cos(x);}
function draw() {
const t = Date.now();
// The dwitter version (smoke instead of fire)
/*
w=1000
c.width=w
x.globalAlpha=.1
for(y=0;y<w;y++){a=(t+y)%w
d=(S(t-a)*w%1)*6
x.fillRect(d%.1*w+(w+C(d)*a)/2,(w+S(d)*a)/2-a*a/w,70,70)}
*/
c.width = c.width;
x.fillRect(0, 0, c.width, c.height);
x.globalCompositeOperation='lighter';
gradient = x.createRadialGradient(size, size, size*0.4, size, size, size);
gradient.addColorStop(0, '#421')
gradient.addColorStop(1, '#000')
x.fillStyle = gradient;
phase1 = 0;
phase2 = 0;
for (var particle=0; particle < particles; particle++ ) {
age = (t + particle*rate) % lifespan;
birth = t-age;
// generate a pseudo-random number between 0 and 2pi,seeded by the particle's birth time
d = Math.sin(birth) * 10000;
d = (d - Math.floor(d)) * 6.28;
// particle's velocity at birth
vx = Math.cos(d) * v_scale;
vy = Math.sin(d) * v_scale;
// position at time t
i = c.width/2 - 3.14*base + phase1*base + vx * age;
j = 900 + vy * age + Math.max(g*age*age,-600);
// decay
x.globalAlpha=(lifespan-age)/lifespan;
x.save();
x.translate(i,j);
x.fillRect(0, 0, size*2, size*2);
x.restore();
phase2 = phase1;
phase1 = d;
}
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);