firework.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. (function ($) {
  2. $.fn.fireworks = function (options) {
  3. options = options || {};
  4. options.width = options.width || $(this).width();
  5. options.height = options.height || $(this).height();
  6. var fireworksField = this,
  7. SCREEN_WIDTH = options.width,
  8. SCREEN_HEIGHT = options.height,
  9. rockets = [],
  10. particles = [];
  11. var canvas = document.createElement("canvas");
  12. canvas.style.width = SCREEN_WIDTH + 'px';
  13. canvas.style.height = SCREEN_HEIGHT + 'px';
  14. canvas.width = SCREEN_WIDTH;
  15. canvas.height = SCREEN_HEIGHT;
  16. canvas.style.position = 'absolute';
  17. canvas.style.top = '0px';
  18. canvas.style.left = '0px';
  19. var context = canvas.getContext('2d');
  20. var mousePos = {};
  21. var gravity = 0.05;
  22. var raf;
  23. $(fireworksField).append(canvas);
  24. document.onmousemove = mouseMove;
  25. setInterval(launch, 2000);
  26. raf = window.requestAnimationFrame(loop);
  27. function mouseMove(ev) {
  28. ev = ev || window.event;
  29. mousePos = mousePosition(ev);
  30. }
  31. function mousePosition(ev) {
  32. if (ev.pageX || ev.pageY) {
  33. return {
  34. x: ev.pageX,
  35. y: ev.pageY
  36. };
  37. }
  38. return {
  39. x: ev.clientX + document.body.scrollLeft - document.body.clientLeft,
  40. y: ev.clientY + document.body.scrollTop - document.body.clientTop
  41. };
  42. }
  43. function launch() {
  44. if (rockets.length < 10) {
  45. var rocket = new Rocket(SCREEN_WIDTH / 2);
  46. rocket.v.x = Math.random() * 6 - 3;
  47. rocket.v.y = Math.random() * -30 - 4;
  48. rocket.color = Math.floor(Math.random() * 360 / 10) * 10;
  49. rockets.push(rocket);
  50. }
  51. }
  52. function loop() {
  53. var existRockets = [];
  54. var existParticles = [];
  55. if (SCREEN_WIDTH != window.innerWidth) {
  56. canvas.width = SCREEN_WIDTH = window.innerWidth;
  57. }
  58. if (SCREEN_HEIGHT != window.innerHeight) {
  59. canvas.height = SCREEN_HEIGHT = window.innerHeight;
  60. }
  61. context.fillStyle = "rgba(0,0,0,0.05)";
  62. context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  63. for (var i = 0; i < rockets.length; i++) {
  64. rockets[i].update();
  65. rockets[i].render(context);
  66. var distance = Math.sqrt(Math.pow(mousePos.x - rockets[i].pos.x, 2) + Math.pow(mousePos.y -
  67. rockets[i].pos.y, 2));
  68. var randomChance = (rockets[i].pos.y < SCREEN_HEIGHT / 2) ? (Math.random() * 100 <= 1) : false;
  69. if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || distance <= 50 || randomChance) {
  70. rockets[i].explode();
  71. } else {
  72. existRockets.push(rockets[i]);
  73. }
  74. }
  75. rockets = existRockets;
  76. for (var i = 0; i < particles.length; i++) {
  77. particles[i].update();
  78. if (particles[i].exist()) {
  79. particles[i].render(context);
  80. existParticles.push(particles[i]);
  81. }
  82. }
  83. particles = existParticles;
  84. raf = window.requestAnimationFrame(loop);
  85. }
  86. function Particle(pos) {
  87. this.pos = {
  88. x: pos ? pos.x : 0,
  89. y: pos ? pos.y : 0
  90. };
  91. this.v = {
  92. x: 0,
  93. y: 0
  94. };
  95. this.resistance = 0.005;
  96. this.size = 5;
  97. this.shrink = 0.99;
  98. this.alpha = 1;
  99. this.fade = 0.97;
  100. this.color = "";
  101. }
  102. Particle.prototype.update = function () {
  103. this.v.x += this.resistance;
  104. this.v.y -= this.resistance;
  105. this.v.y += gravity;
  106. this.pos.x += this.v.x;
  107. this.pos.y += this.v.y;
  108. this.size *= this.shrink;
  109. this.alpha *= this.fade;
  110. }
  111. Particle.prototype.render = function () {
  112. var x = this.pos.x,
  113. y = this.pos.y,
  114. r = this.size / 2;
  115. var gradient = context.createRadialGradient(x, y, 0.1, x, y, r);
  116. gradient.addColorStop(0, "rgba(255, 255, 255, " + this.alpha + ")");
  117. gradient.addColorStop(0.9, "hsla(" + this.color + ", 100%, 50%, 1)");
  118. gradient.addColorStop(1, "rgba(0, 0, 0, 1)");
  119. context.fillStyle = gradient;
  120. context.beginPath();
  121. context.arc(x, y, r, 0, 2 * Math.PI, true);
  122. context.closePath();
  123. context.fill();
  124. }
  125. Particle.prototype.exist = function () {
  126. if (this.alpha >= 0.02 && this.size > 0.8) {
  127. return true;
  128. } else {
  129. return false;
  130. }
  131. }
  132. function Rocket(x) {
  133. Particle.apply(this, [{
  134. x: x,
  135. y: SCREEN_HEIGHT
  136. }]);
  137. }
  138. (function () {
  139. var Super = function () {};
  140. Super.prototype = Particle.prototype;
  141. Rocket.prototype = new Super();
  142. })();
  143. Rocket.prototype.constructor = Rocket;
  144. Rocket.prototype.update = function () {
  145. this.pos.x += this.v.x;
  146. this.pos.y += this.v.y;
  147. }
  148. Rocket.prototype.render = function (context) {
  149. var x = this.pos.x,
  150. y = this.pos.y,
  151. r = this.size / 2;
  152. var gradient = context.createRadialGradient(x, y, 0.1, x, y, r);
  153. gradient.addColorStop(0, "#ffff00");
  154. gradient.addColorStop(1, "rgba(0, 0, 0, 1)");
  155. context.fillStyle = gradient;
  156. context.beginPath();
  157. context.arc(x, y, r, 0, 2 * Math.PI, true);
  158. context.closePath();
  159. context.fill();
  160. }
  161. Rocket.prototype.explode = function () {
  162. var count = getGaussianDistributionNumber(240, 20);
  163. for (var i = 0; i <= count; i++) {
  164. var particle = new Particle(this.pos);
  165. var angle = Math.random() * Math.PI * 2;
  166. var speed = getGaussianDistributionNumber(2.5, 0.3);
  167. particle.size = 3;
  168. particle.v.x = Math.cos(angle) * speed;
  169. particle.v.y = Math.sin(angle) * speed;
  170. particle.color = this.color;
  171. particles.push(particle);
  172. }
  173. }
  174. function getGaussianDistributionNumber(mean, std_dev) {
  175. var U1 = -Math.random() + 1;
  176. var U2 = -Math.random() + 1;
  177. var R = Math.sqrt(-2 * Math.log(U2));
  178. var a = 2 * Math.PI * U1;
  179. var Z = R * Math.cos(a);
  180. return mean + (Z * std_dev);
  181. }
  182. }
  183. }(jQuery));