diff --git a/fireworks.js b/fireworks.js new file mode 100644 index 0000000..dc3790d --- /dev/null +++ b/fireworks.js @@ -0,0 +1,235 @@ +window.requestAnimFrame = (function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + }; +})(); + +var canvas = null, + ctx = null, + cw = window.innerWidth, + ch = window.innerHeight, + fireworksLimit = 10, + fireworksShown = 0, + fireworks = [], + particles = [], + hue = 120, + timerTotal = 25, + timerTick = 0, + animationEnd = true; + +function random(min, max) { + return Math.random() * (max - min) + min; +} + +/* To sprawdzic... */ +function calculateDistance(p1x, p1y, p2x, p2y) { + var xDistance = p1x - p2x, + yDistance = p1y - p2y; + return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2)); +} + +function Firework(sx, sy, tx, ty) { + this.x = sx; + this.y = sy; + + this.sx = sx; + this.sy = sy; + + this.tx = tx; + this.ty = ty; + + this.distanceToTarget = calculateDistance(sx, sy, tx, ty); + this.distanceTraveled = 0; + + this.coordinates = []; + this.coordinateCount = 3; + + while (this.coordinateCount--) { + this.coordinates.push([this.x, this.y]); + } + + this.angle = Math.atan2(ty - sy, tx - sx); + this.speed = 2; + this.acceleration = 1.05; + this.brightness = random(50, 70); + this.targetRadius = 1; +} + +Firework.prototype.update = function (index) { + this.coordinates.pop(); + this.coordinates.unshift([this.x, this.y]); + + if (this.targetRadius < 8) { + this.targetRadius += 0.3; + } else { + this.targetRadius = 1; + } + + // speed up the firework + this.speed *= this.acceleration; + + // get the current velocities based on angle and speed + var vx = Math.cos(this.angle) * this.speed, + vy = Math.sin(this.angle) * this.speed; + // how far will the firework have traveled with velocities applied? + this.distanceTraveled = calculateDistance(this.sx, this.sy, this.x + vx, this.y + vy); + + if (this.distanceTraveled >= this.distanceToTarget) { + createParticles(this.tx, this.ty); + // remove the firework, use the index passed into the update function to determine which to remove + fireworks.splice(index, 1); + } else { + // target not reached, keep traveling + this.x += vx; + this.y += vy; + } +} + +// draw firework +Firework.prototype.draw = function () { + ctx.beginPath(); + // move to the last tracked coordinate in the set, then draw a line to the current x and y + ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]); + ctx.lineTo(this.x, this.y); + ctx.strokeStyle = 'hsl(' + hue + ', 100%, ' + this.brightness + '%)'; + ctx.stroke(); +} + +function Particle(x, y) { + this.x = x; + this.y = y; + // track the past coordinates of each particle to create a trail effect, increase the coordinate count to create more prominent trails + this.coordinates = []; + this.coordinateCount = 5; + while (this.coordinateCount--) { + this.coordinates.push([this.x, this.y]); + } + // set a random angle in all possible directions, in radians + this.angle = random(0, Math.PI * 2); + this.speed = random(1, 10); + // friction will slow the particle down + this.friction = 0.98; + // gravity will be applied and pull the particle down + this.gravity = 1; + // set the hue to a random number +-50 of the overall hue variable + this.hue = random(hue - 50, hue + 50); + this.brightness = random(50, 80); + this.alpha = 1; + // set how fast the particle fades out + this.decay = random(0.015, 0.03); +} + +// update particle +Particle.prototype.update = function (index) { + // remove last item in coordinates array + this.coordinates.pop(); + // add current coordinates to the start of the array + this.coordinates.unshift([this.x, this.y]); + // slow down the particle + this.speed *= this.friction; + // apply velocity + this.x += Math.cos(this.angle) * this.speed; + this.y += Math.sin(this.angle) * this.speed + this.gravity; + // fade out the particle + this.alpha -= this.decay; + + // remove the particle once the alpha is low enough, based on the passed in index + if (this.alpha <= this.decay) { + particles.splice(index, 1); + } + + if (particles.length === 0) { + if (fireworksShown === fireworksLimit) { + animationEnd = true; + } + } +} + +// draw particle +Particle.prototype.draw = function () { + ctx.beginPath(); + // move to the last tracked coordinates in the set, then draw a line to the current x and y + ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]); + ctx.lineTo(this.x, this.y); + ctx.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')'; + ctx.stroke(); +} + +// create particle group/explosion +function createParticles(x, y) { + // increase the particle count for a bigger explosion, beware of the canvas performance hit with the increased particles though + var particleCount = 500; + while (particleCount--) { + particles.push(new Particle(x, y)); + } +} + +function loop() { + if (animationEnd === true) { + animationFinish(); + return true; + } + + requestAnimationFrame(loop); + hue = random(0, 360); + + ctx.globalCompositeOperation = 'destination-out'; + ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; + ctx.fillRect(0, 0, cw, ch); + ctx.globalCompositeOperation = 'lighter'; + + var i = fireworks.length; + while (i--) { + fireworks[i].draw(); + fireworks[i].update(i); + } + + var i = particles.length; + while (i--) { + particles[i].draw(); + particles[i].update(i); + } + + if (timerTick >= timerTotal) { + // start the firework at the bottom middle of the screen, then set the random target coordinates, the random y coordinates will be set within the range of the top half of the screen + if (fireworksShown < fireworksLimit) { + fireworks.push(new Firework(cw / 2, ch, random(0, cw), random(0, ch / 2))); + fireworksShown++; + timerTick = 0; + } + } else { + timerTick++; + } +} + +//window.onload = loop; +window.fireworks.start = function () { + /* Prevent multiple animations */ + if (animationEnd === false) { + return false; + } + + fireworksShown = 0; + animationEnd = false; + canvas = document.createElement('canvas'); + document.body.appendChild(canvas); + ctx = canvas.getContext('2d'); + canvas.style.zIndex = 100; + canvas.style.top = 0; + canvas.style.left = 0; + canvas.style.position = 'fixed'; + canvas.width = cw; + canvas.height = ch; + //canvas.style.background = "rgba(0,0,0,0.7)"; + + loop(); + + //setTimeout(function(){animationEnd = true;}, 4500); +} + +animationFinish = function () { + document.body.removeChild(canvas); +}; diff --git a/index.html b/index.html index b577b4b..41d4549 100644 --- a/index.html +++ b/index.html @@ -9,11 +9,57 @@ +
+ | + | + | + | + |
+ | + | + | + | + |
+ | + |
+ |
+ + | + |
+ | + | + | + | + |
+ | + | + | + | + |
Seeed: 📋
+