JSFiddle - React, Tailwind, and code Playground
HTML
<div><canvas class="game"></canvas></div>
<div><canvas class="game"></canvas></div>
<div><canvas class="game"></canvas></div>
JavaScript
class Fire {
constructor(options) {
Object.assign(this, options);
this.particles = [];
this.stage = this.canvas.getContext("2d");
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.style.width = this.width + "px";
this.canvas.style.height = this.height + "px";
this.stage.globalCompositeOperation = "lighter";
this.timer = setInterval(this.update, 40);
}
update = () => {
this.particles.push(...[...Array(10)].map(() =>
new Particle(
this.width / 2,
this.height * 0.8,
(Math.random() * 2 * this.speed - this.speed) / 2,
-Math.random() * 2 * this.speed
)
));
this.stage.clearRect(0, 0, this.width, this.height);
for (let i = 0; i < this.particles.length; i++) {
const p = this.particles[i];
this.stage.fillStyle = "rgba("+(260-(p.life*2))+","+((p.life*2)+50)+","+(p.life*2)+","+(((this.max-p.life)/this.max)*0.4)+")";
this.stage.beginPath();
this.stage.arc(p.x, p.y, (this.max - p.life) / this.max * (this.size / 2) + (this.size / 2), 0, 2 * Math.PI);
this.stage.fill();
p.x += p.xs;
p.y += p.ys;
p.life++;
if (p.life >= this.max) {
this.particles.splice(i, 1);
i--;
}
}
}
}
function Particle(x, y, xs, ys) {
this.x = x;
this.y = y;
this.xs = xs;
this.ys = ys;
this.life = 0;
}
const fires = [...document.querySelectorAll('.game')].map((n, i) => new Fire({
canvas: n,
width: (i + 1) * 50,
height: (i + 1) * 50,
max: (i + 1) * 30,
size: i + 2,
speed: i + 3,
}));