Created
December 31, 2019 17:22
-
-
Save onequbit/ca51bb4315a91991ac5488ec317eefe8 to your computer and use it in GitHub Desktop.
Fireworks - taken from https://jsfiddle.net/dtrooper/AceJJ/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE HTML> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Fireworks!</title> | |
</head> | |
<style> | |
body { | |
background-color: #000000; | |
margin: 0px; | |
overflow: hidden; | |
} | |
</style> | |
<body/> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> | |
<script> | |
var SCREEN_WIDTH = window.innerWidth, | |
SCREEN_HEIGHT = window.innerHeight, | |
mousePos = { | |
x: 400, | |
y: 300 | |
}, | |
// create canvas | |
canvas = document.createElement('canvas'), | |
context = canvas.getContext('2d'), | |
particles = [], | |
rockets = [], | |
MAX_PARTICLES = 400, | |
colorCode = 0; | |
// init | |
$(document).ready(function() { | |
document.body.appendChild(canvas); | |
canvas.width = SCREEN_WIDTH; | |
canvas.height = SCREEN_HEIGHT; | |
setInterval(launch, 800); | |
setInterval(loop, 1000 / 50); | |
}); | |
// update mouse position | |
$(document).mousemove(function(e) { | |
e.preventDefault(); | |
mousePos = { | |
x: e.clientX, | |
y: e.clientY | |
}; | |
}); | |
// launch more rockets!!! | |
$(document).mousedown(function(e) { | |
for (var i = 0; i < 5; i++) { | |
launchFrom(Math.random() * SCREEN_WIDTH * 2 / 3 + SCREEN_WIDTH / 6); | |
} | |
}); | |
function launch() { | |
launchFrom(mousePos.x); | |
} | |
function launchFrom(x) { | |
if (rockets.length < 10) { | |
var rocket = new Rocket(x); | |
rocket.explosionColor = Math.floor(Math.random() * 36) * 10; | |
rocket.vel.y = Math.random() * -3 - 4; | |
rocket.vel.x = Math.random() * 6 - 3; | |
rocket.size = 8; | |
rocket.shrink = 0.999; | |
rocket.gravity = 0.01; | |
rockets.push(rocket); | |
} | |
} | |
function loop() { | |
// update screen size | |
if (SCREEN_WIDTH != window.innerWidth) { | |
canvas.width = SCREEN_WIDTH = window.innerWidth; | |
} | |
if (SCREEN_HEIGHT != window.innerHeight) { | |
canvas.height = SCREEN_HEIGHT = window.innerHeight; | |
} | |
// clear canvas | |
context.fillStyle = "rgba(0, 0, 0, 0.05)"; | |
context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | |
var existingRockets = []; | |
for (var i = 0; i < rockets.length; i++) { | |
// update and render | |
rockets[i].update(); | |
rockets[i].render(context); | |
// calculate distance with Pythagoras | |
var distance = Math.sqrt(Math.pow(mousePos.x - rockets[i].pos.x, 2) + Math.pow(mousePos.y - rockets[i].pos.y, 2)); | |
// random chance of 1% if rockets is above the middle | |
var randomChance = rockets[i].pos.y < (SCREEN_HEIGHT * 2 / 3) ? (Math.random() * 100 <= 1) : false; | |
/* Explosion rules | |
- 80% of screen | |
- going down | |
- close to the mouse | |
- 1% chance of random explosion | |
*/ | |
if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || rockets[i].vel.y >= 0 || distance < 50 || randomChance) { | |
rockets[i].explode(); | |
} else { | |
existingRockets.push(rockets[i]); | |
} | |
} | |
rockets = existingRockets; | |
var existingParticles = []; | |
for (var i = 0; i < particles.length; i++) { | |
particles[i].update(); | |
// render and save particles that can be rendered | |
if (particles[i].exists()) { | |
particles[i].render(context); | |
existingParticles.push(particles[i]); | |
} | |
} | |
// update array with existing particles - old particles should be garbage collected | |
particles = existingParticles; | |
while (particles.length > MAX_PARTICLES) { | |
particles.shift(); | |
} | |
} | |
function Particle(pos) { | |
this.pos = { | |
x: pos ? pos.x : 0, | |
y: pos ? pos.y : 0 | |
}; | |
this.vel = { | |
x: 0, | |
y: 0 | |
}; | |
this.shrink = .97; | |
this.size = 2; | |
this.resistance = 1; | |
this.gravity = 0; | |
this.flick = false; | |
this.alpha = 1; | |
this.fade = 0; | |
this.color = 0; | |
} | |
Particle.prototype.update = function() { | |
// apply resistance | |
this.vel.x *= this.resistance; | |
this.vel.y *= this.resistance; | |
// gravity down | |
this.vel.y += this.gravity; | |
// update position based on speed | |
this.pos.x += this.vel.x; | |
this.pos.y += this.vel.y; | |
// shrink | |
this.size *= this.shrink; | |
// fade out | |
this.alpha -= this.fade; | |
}; | |
Particle.prototype.render = function(c) { | |
if (!this.exists()) { | |
return; | |
} | |
c.save(); | |
c.globalCompositeOperation = 'lighter'; | |
var x = this.pos.x, | |
y = this.pos.y, | |
r = this.size / 2; | |
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r); | |
gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")"); | |
gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")"); | |
gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)"); | |
c.fillStyle = gradient; | |
c.beginPath(); | |
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true); | |
c.closePath(); | |
c.fill(); | |
c.restore(); | |
}; | |
Particle.prototype.exists = function() { | |
return this.alpha >= 0.1 && this.size >= 1; | |
}; | |
function Rocket(x) { | |
Particle.apply(this, [{ | |
x: x, | |
y: SCREEN_HEIGHT}]); | |
this.explosionColor = 0; | |
} | |
Rocket.prototype = new Particle(); | |
Rocket.prototype.constructor = Rocket; | |
Rocket.prototype.explode = function() { | |
var count = Math.random() * 10 + 80; | |
for (var i = 0; i < count; i++) { | |
var particle = new Particle(this.pos); | |
var angle = Math.random() * Math.PI * 2; | |
// emulate 3D effect by using cosine and put more particles in the middle | |
var speed = Math.cos(Math.random() * Math.PI / 2) * 15; | |
particle.vel.x = Math.cos(angle) * speed; | |
particle.vel.y = Math.sin(angle) * speed; | |
particle.size = 10; | |
particle.gravity = 0.2; | |
particle.resistance = 0.92; | |
particle.shrink = Math.random() * 0.05 + 0.93; | |
particle.flick = true; | |
particle.color = this.explosionColor; | |
particles.push(particle); | |
} | |
}; | |
Rocket.prototype.render = function(c) { | |
if (!this.exists()) { | |
return; | |
} | |
c.save(); | |
c.globalCompositeOperation = 'lighter'; | |
var x = this.pos.x, | |
y = this.pos.y, | |
r = this.size / 2; | |
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r); | |
gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")"); | |
gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")"); | |
c.fillStyle = gradient; | |
c.beginPath(); | |
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size / 2 + this.size / 2 : this.size, 0, Math.PI * 2, true); | |
c.closePath(); | |
c.fill(); | |
c.restore(); | |
}; | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment