<canvas></canvas>
body {
  overflow:hidden;
  margin:0;
}
var canvas = document.querySelector('canvas');
var W = window.innerWidth;
var H = window.innerHeight;

var c = canvas.getContext('2d');

function random(min,max,int) {
	if (int) {
		return Math.floor(Math.random()*(max-min+1)+min);
	}
	else {
		return Math.random()*(max-min)+min;
	}
}

window.addEventListener('click',function() {
	for (var i = 0; i < 20; i++) {
		var f = new Firework();
		fireworks.push(f);
	}
});

window.addEventListener('resize',function() {
	W = window.innerWidth;
	H = window.innerHeight;
	
	init();
});


var colorArray = [
  'rgb(255, 0, 219)',
  'rgb(0, 223, 255)',
  'rgb(0, 255, 107)',
  'rgb(253, 255, 0)',
  'rgb(124, 0, 255)'
];
var fireworks;
var particles;
var gravity = 0.25;
var particleGrav = 0.025;
var speed = -H/40;

function init() {
	canvas.width = W;
	canvas.height = H;
	
	fireworks = [];
	particles = [];
}

function Firework() {
	radius = 3;
	var x = random(0+radius,W-radius);
	var y = H-radius;
	var dx = 0;
	var dy = random(speed,speed/2);
	this.color = colorArray[Math.floor((Math.random() * colorArray.length))];;
	
	this.p = new Particle(x,y,dx,dy,radius,this.color,null);
	
	this.shouldExplode = function() {
		return this.p.dy > -1.5;
	}
	
	this.explode = function() {
		var parts = random(50,100,true);
		for (var i = 0; i < parts; i++) {
			var part = new Particle(this.p.x,this.p.y,random(-1,1),random(-1,-2.5),1,this.color,100);
			particles.push(part);
		}
	}
	
}

function Particle(x,y,dx,dy,radius,color,lifespan) {
	this.x = x;
	this.y = y;
	this.dx = dx;
	this.dy = dy;
	this.radius = radius;
	this.color = color;
	this.lifespan = lifespan;
	
	this.update = function() {
		this.x += this.dx;
		this.y += this.dy;
		if (this.lifespan) {
			this.lifespan--;
			this.dy += particleGrav;
		}
		else {
			this.dy += gravity;
		}
		this.draw();
	}
	
	this.draw = function() {
		c.beginPath();
		c.arc(this.x,this.y,this.radius,0,Math.PI*2,false);
		c.fillStyle = this.color;
		if (this.lifespan) {
			c.globalAlpha = this.lifespan/100;
		}
		else {
			c.globalAlpha = 1;
		}
		c.fill();
		c.closePath();
	}
}


function animate() {
	// animate
	requestAnimationFrame(animate);
	// partially clear screen for trail effect
	c.fillStyle = 'rgba(0,0,0,0.25)';
	c.fillRect(0,0,W,H);
	// 10% chance to spawn new firework
	if (random(0,10,true) == 1) {
		var f = new Firework();
		fireworks.push(f);
	}
	for (var i = 0; i < fireworks.length; i++) {
		fireworks[i].p.update();
		if (fireworks[i].shouldExplode()) {
			fireworks[i].explode();
			fireworks.splice(i,1);
		}
	}
	for(var i = 0; i < particles.length; i++) {
		particles[i].update();
		if (particles[i].lifespan == 1) {
			particles.splice(i,1);
		}
	}
	
}

init();
animate();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.