1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title></title>
5 </head>
6 <body style=" background-color: #000;">
7 <canvas id="canvas"></canvas>
8
9 <script>
10 window.requestAnimFrame = ( function() {
11 return window.requestAnimationFrame ||
12 window.webkitRequestAnimationFrame ||
13 window.mozRequestAnimationFrame ||
14 function( callback ) {
15 window.setTimeout( callback, 1000 / 60 );
16 };
17 })();
18 var canvas = document.getElementById( 'canvas' ),
19 ctx = canvas.getContext( '2d' ),
20 cw = window.innerWidth,
21 ch = window.innerHeight,
22 fireworks = [],
23 particles = [],
24 hue = 120,
25 limiterTotal = 5,
26 limiterTick = 0,
27 timerTotal = 80,
28 timerTick = 0,
29 mousedown = false,
30 mx,
31 my;
32
33 canvas.width = cw;
34 canvas.height = ch;
35
36 function random( min, max ) {
37 return Math.random() * ( max - min ) + min;
38 }
39
40 function calculateDistance( p1x, p1y, p2x, p2y ) {
41 var xDistance = p1x - p2x,
42 yDistance = p1y - p2y;
43 return Math.sqrt( Math.pow( xDistance, 2 ) + Math.pow( yDistance, 2 ) );
44 }
45
46 function Firework( sx, sy, tx, ty ) {
47
48 this.x = sx;
49 this.y = sy;
50
51 this.sx = sx;
52 this.sy = sy;
53
54 this.tx = tx;
55 this.ty = ty;
56
57 this.distanceToTarget = calculateDistance( sx, sy, tx, ty );
58 this.distanceTraveled = 0;
59
60 this.coordinates = [];
61 this.coordinateCount = 3;
62
63 while( this.coordinateCount-- ) {
64 this.coordinates.push( [ this.x, this.y ] );
65 }
66 this.angle = Math.atan2( ty - sy, tx - sx );
67 this.speed = 2;
68 this.acceleration = 1.05;
69 this.brightness = random( 50, 70 );
70
71 this.targetRadius = 1;
72 }
73
74
75 Firework.prototype.update = function( index ) {
76
77 this.coordinates.pop();
78
79 this.coordinates.unshift( [ this.x, this.y ] );
80
81 if( this.targetRadius < 8 ) {
82 this.targetRadius += 0.3;
83 } else {
84 this.targetRadius = 1;
85 }
86
87 this.speed *= this.acceleration;
88
89 var vx = Math.cos( this.angle ) * this.speed,
90 vy = Math.sin( this.angle ) * this.speed;
91
92 this.distanceTraveled = calculateDistance( this.sx, this.sy, this.x + vx, this.y + vy );
93
94 if( this.distanceTraveled >= this.distanceToTarget ) {
95 createParticles( this.tx, this.ty );
96 fireworks.splice( index, 1 );
97 } else {
98 this.x += vx;
99 this.y += vy;
100 }
101 }
102
103 Firework.prototype.draw = function() {
104 ctx.beginPath();
105 ctx.moveTo( this.coordinates[ this.coordinates.length - 1][ 0 ], this.coordinates[ this.coordinates.length - 1][ 1 ] );
106 ctx.lineTo( this.x, this.y );
107 ctx.strokeStyle = 'hsl(' + hue + ', 100%, ' + this.brightness + '%)';
108 ctx.stroke();
109
110 ctx.beginPath();
111 ctx.arc( this.tx, this.ty, this.targetRadius, 0, Math.PI * 2 );
112 ctx.stroke();
113 }
114
115 function Particle( x, y ) {
116 this.x = x;
117 this.y = y;
118
119 this.coordinates = [];
120 this.coordinateCount = 5;
121 while( this.coordinateCount-- ) {
122 this.coordinates.push( [ this.x, this.y ] );
123 }
124
125 this.angle = random( 0, Math.PI * 2 );
126 this.speed = random( 1, 10 );
127
128 this.friction = 0.95;
129 this.gravity = 1;
130
131 this.hue = random( hue - 20, hue + 20 );
132 this.brightness = random( 50, 80 );
133 this.alpha = 1;
134 this.decay = random( 0.015, 0.03 );
135 //this.decay = 0;
136 }
137
138 Particle.prototype.update = function( index ) {
139
140 this.coordinates.pop();
141 this.coordinates.unshift( [ this.x, this.y ] );
142 this.speed *= this.friction;
143 this.x += Math.cos( this.angle ) * this.speed;
144 this.y += Math.sin( this.angle ) * this.speed + this.gravity;
145 this.alpha -= this.decay;
146
147 if( this.alpha <= this.decay ) {
148 particles.splice( index, 1 );
149 }
150 }
151
152 Particle.prototype.draw = function() {
153 ctx. beginPath();
154 ctx.moveTo( this.coordinates[ this.coordinates.length - 1 ][ 0 ], this.coordinates[ this.coordinates.length - 1 ][ 1 ] );
155 ctx.lineTo( this.x, this.y );
156 ctx.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')';
157 ctx.stroke();
158 }
159
160 function createParticles( x, y ) {
161 var particleCount = 30;
162 while( particleCount-- ) {
163 particles.push( new Particle( x, y ) );
164 }
165 }
166
167
168 function loop() {
169 requestAnimFrame( loop );
170
171 hue += 0.5;
172
173 ctx.globalCompositeOperation = 'destination-out';
174 ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
175 ctx.fillRect( 0, 0, cw, ch );
176 ctx.globalCompositeOperation = 'lighter';
177
178 var i = fireworks.length;
179 while( i-- ) {
180 fireworks[ i ].draw();
181 fireworks[ i ].update( i );
182 }
183
184 var i = particles.length;
185 while( i-- ) {
186 particles[ i ].draw();
187 particles[ i ].update( i );
188 }
189
190 if( timerTick >= timerTotal ) {
191 if( !mousedown ) {
192 fireworks.push( new Firework( cw / 2, ch, random( 0, cw ), random( 0, ch / 2 ) ) );
193 timerTick = 0;
194 }
195 } else {
196 timerTick++;
197 }
198
199 if( limiterTick >= limiterTotal ) {
200 if( mousedown ) {
201 fireworks.push( new Firework( cw / 2, ch, mx, my ) );
202 limiterTick = 0;
203 }
204 } else {
205 limiterTick++;
206 }
207 }
208
209 canvas.addEventListener( 'mousemove', function( e ) {
210 mx = e.pageX - canvas.offsetLeft;
211 my = e.pageY - canvas.offsetTop;
212 });
213
214 canvas.addEventListener( 'mousedown', function( e ) {
215 e.preventDefault();
216 mousedown = true;
217 });
218
219 canvas.addEventListener( 'mouseup', function( e ) {
220 e.preventDefault();
221 mousedown = false;
222 });
223
224 window.onload = loop;
225 </script>
226 </body>
227 </html>