fork(297) download
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <HTML>
  3.  
  4. <HEAD>
  5. <TITLE>I Love You</TITLE>
  6. <META NAME="Generator" CONTENT="EditPlus">
  7. <META NAME="Author" CONTENT="">
  8. <META NAME="Keywords" CONTENT="">
  9. <META NAME="Description" CONTENT="">
  10. <style>
  11. html,
  12. body {
  13. overflow: hidden;
  14. padding: 0;
  15. margin: 0;
  16. background: #000;
  17. }
  18.  
  19. canvas {
  20. position: absolute;
  21. width: 100%;
  22. height: 100%;
  23. }
  24.  
  25. canvas {
  26. /* top: 50%;
  27. left: 50%; */
  28. z-index: 1;
  29. display: block;
  30. position: absolute;
  31. transform: translate(-50%, -50%);
  32. animation: heart 1.75s ease infinite
  33. }
  34.  
  35. @keyframes heart {
  36. 0% {
  37. transform: scale(1.2);
  38. }
  39. 30% {
  40. transform: scale(0.9);
  41. }
  42. 80% {
  43. transform: scale(1.0);
  44. }
  45. 100% {
  46. transform: scale(1.2);
  47. }
  48. }
  49. </style>
  50. </HEAD>
  51.  
  52. <BODY>
  53.  
  54. <canvas id="pinkboard">
  55. <canvas id="pinkboard">
  56. </canvas>
  57. </canvas>
  58. <script>
  59. /*
  60. * Settings
  61. */
  62. var settings = {
  63. particles: {
  64. length: 3500, // maximum amount of particles
  65. duration: 2.5, // particle duration in sec
  66. velocity: 136, // particle velocity in pixels/sec
  67. effect: -0.95, // play with this for a nice effect
  68. size: 13, // particle size in pixels
  69. },
  70. };
  71.  
  72. /*
  73. * RequestAnimationFrame polyfill by Erik Möller
  74. */
  75. (function() {
  76. var b = 0;
  77. var c = ["ms", "moz", "webkit", "o"];
  78. for (var a = 0; a < c.length && !window.requestAnimationFrame; ++a) {
  79. window.requestAnimationFrame = window[c[a] + "RequestAnimationFrame"];
  80. window.cancelAnimationFrame = window[c[a] + "CancelAnimationFrame"] || window[c[a] + "CancelRequestAnimationFrame"]
  81. }
  82. if (!window.requestAnimationFrame) {
  83. window.requestAnimationFrame = function(h, e) {
  84. var d = new Date().getTime();
  85. var f = Math.max(0, 16 - (d - b));
  86. var g = window.setTimeout(function() {
  87. h(d + f)
  88. }, f);
  89. b = d + f;
  90. return g
  91. }
  92. }
  93. if (!window.cancelAnimationFrame) {
  94. window.cancelAnimationFrame = function(d) {
  95. clearTimeout(d)
  96. }
  97. }
  98. }());
  99.  
  100. /*
  101. * Point class
  102. */
  103. var Point = (function() {
  104. function Point(x, y) {
  105. this.x = (typeof x !== 'undefined') ? x : 0;
  106. this.y = (typeof y !== 'undefined') ? y : 0;
  107. }
  108. Point.prototype.clone = function() {
  109. return new Point(this.x, this.y);
  110. };
  111. Point.prototype.length = function(length) {
  112. if (typeof length == 'undefined')
  113. return Math.sqrt(this.x * this.x + this.y * this.y);
  114. this.normalize();
  115. this.x *= length;
  116. this.y *= length;
  117. return this;
  118. };
  119. Point.prototype.normalize = function() {
  120. var length = this.length();
  121. this.x /= length;
  122. this.y /= length;
  123. return this;
  124. };
  125. return Point;
  126. })();
  127.  
  128. /*
  129. * Particle class
  130. */
  131. var Particle = (function() {
  132. function Particle() {
  133. this.position = new Point();
  134. this.velocity = new Point();
  135. this.acceleration = new Point();
  136. this.age = 0;
  137. }
  138. Particle.prototype.initialize = function(x, y, dx, dy) {
  139. this.position.x = x;
  140. this.position.y = y;
  141. this.velocity.x = dx;
  142. this.velocity.y = dy;
  143. this.acceleration.x = dx * settings.particles.effect;
  144. this.acceleration.y = dy * settings.particles.effect;
  145. this.age = 0;
  146. };
  147. Particle.prototype.update = function(deltaTime) {
  148. this.position.x += this.velocity.x * deltaTime;
  149. this.position.y += this.velocity.y * deltaTime;
  150. this.velocity.x += this.acceleration.x * deltaTime;
  151. this.velocity.y += this.acceleration.y * deltaTime;
  152. this.age += deltaTime;
  153. };
  154. Particle.prototype.draw = function(context, image) {
  155. function ease(t) {
  156. return (--t) * t * t + 1;
  157. }
  158. var size = image.width * ease(this.age / settings.particles.duration);
  159. context.globalAlpha = 1 - this.age / settings.particles.duration;
  160. context.drawImage(image, this.position.x - size / 2, this.position.y - size / 2, size, size);
  161. };
  162. return Particle;
  163. })();
  164.  
  165. /*
  166. * ParticlePool class
  167. */
  168. var ParticlePool = (function() {
  169. var particles,
  170. firstActive = 0,
  171. firstFree = 0,
  172. duration = settings.particles.duration;
  173.  
  174. function ParticlePool(length) {
  175. // create and populate particle pool
  176. particles = new Array(length);
  177. for (var i = 0; i < particles.length; i++)
  178. particles[i] = new Particle();
  179. }
  180. ParticlePool.prototype.add = function(x, y, dx, dy) {
  181. particles[firstFree].initialize(x, y, dx, dy);
  182.  
  183. // handle circular queue
  184. firstFree++;
  185. if (firstFree == particles.length) firstFree = 0;
  186. if (firstActive == firstFree) firstActive++;
  187. if (firstActive == particles.length) firstActive = 0;
  188. };
  189. ParticlePool.prototype.update = function(deltaTime) {
  190. var i;
  191.  
  192. // update active particles
  193. if (firstActive < firstFree) {
  194. for (i = firstActive; i < firstFree; i++)
  195. particles[i].update(deltaTime);
  196. }
  197. if (firstFree < firstActive) {
  198. for (i = firstActive; i < particles.length; i++)
  199. particles[i].update(deltaTime);
  200. for (i = 0; i < firstFree; i++)
  201. particles[i].update(deltaTime);
  202. }
  203.  
  204. // remove inactive particles
  205. while (particles[firstActive].age >= duration && firstActive != firstFree) {
  206. firstActive++;
  207. if (firstActive == particles.length) firstActive = 0;
  208. }
  209.  
  210.  
  211. };
  212. ParticlePool.prototype.draw = function(context, image) {
  213. // draw active particles
  214. if (firstActive < firstFree) {
  215. for (i = firstActive; i < firstFree; i++)
  216. particles[i].draw(context, image);
  217. }
  218. if (firstFree < firstActive) {
  219. for (i = firstActive; i < particles.length; i++)
  220. particles[i].draw(context, image);
  221. for (i = 0; i < firstFree; i++)
  222. particles[i].draw(context, image);
  223. }
  224. };
  225. return ParticlePool;
  226. })();
  227.  
  228. /*
  229. * Putting it all together
  230. */
  231. (function(canvas) {
  232. var context = canvas.getContext('2d'),
  233. particles = new ParticlePool(settings.particles.length),
  234. particleRate = settings.particles.length / settings.particles.duration, // particles/sec
  235. time;
  236.  
  237. // get point on heart with -PI <= t <= PI
  238. function pointOnHeart(t) {
  239. return new Point(
  240. 160 * Math.pow(Math.sin(t), 3),
  241. 110 * Math.cos(t) - 50 * Math.cos(2 * t) - 20 * Math.cos(3 * t) - 10 * Math.cos(4 * t) + 25
  242. );
  243. }
  244.  
  245. // creating the particle image using a dummy canvas
  246. var image = (function() {
  247. var canvas = document.createElement('canvas'),
  248. context = canvas.getContext('2d');
  249. canvas.width = settings.particles.size;
  250. canvas.height = settings.particles.size;
  251. // helper function to create the path
  252. function to(t) {
  253. var point = pointOnHeart(t);
  254. point.x = settings.particles.size / 3 + point.x * settings.particles.size / 550;
  255. point.y = settings.particles.size / 3 - point.y * settings.particles.size / 550;
  256. return point;
  257. }
  258. // create the path
  259. context.beginPath();
  260. var t = -Math.PI;
  261. var point = to(t);
  262. context.moveTo(point.x, point.y);
  263. while (t < Math.PI) {
  264. t += 0.01; // baby steps!
  265. point = to(t);
  266. context.lineTo(point.x, point.y);
  267. }
  268. context.closePath();
  269. // create the fill
  270. context.fillStyle = '#ea80b0';
  271. context.fill();
  272. // create the image
  273. var image = new Image();
  274. image.src = canvas.toDataURL();
  275. return image;
  276. })();
  277.  
  278. // render that thing!
  279. function render() {
  280. // next animation frame
  281. requestAnimationFrame(render);
  282.  
  283. // update time
  284. var newTime = new Date().getTime() / 1000,
  285. deltaTime = newTime - (time || newTime);
  286. time = newTime;
  287.  
  288. // clear canvas
  289. context.clearRect(0, 0, canvas.width, canvas.height);
  290.  
  291. // create new particles
  292. var amount = particleRate * deltaTime;
  293. for (var i = 0; i < amount; i++) {
  294. var pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random());
  295. var dir = pos.clone().length(settings.particles.velocity);
  296. particles.add(canvas.width / 2 + pos.x, canvas.height / 2 - pos.y, dir.x, -dir.y);
  297. }
  298.  
  299. // update and draw particles
  300. particles.update(deltaTime);
  301. particles.draw(context, image);
  302. }
  303.  
  304. // handle (re-)sizing of the canvas
  305. function onResize() {
  306. canvas.width = canvas.clientWidth;
  307. canvas.height = canvas.clientHeight;
  308. }
  309. window.onresize = onResize;
  310.  
  311. // delay rendering bootstrap
  312. setTimeout(function() {
  313. onResize();
  314. render();
  315. }, 10);
  316. })(document.getElementById('pinkboard'));
  317. </script>
  318. </BODY>
  319.  
  320. </HTML>
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty