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); };