heart.html 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <html>
  2. <head>
  3. <meta charset="utf-8" />
  4. <title>loveHeart</title>
  5. <link
  6. rel="shortcut icon"
  7. href="http://zhouql.vip/images/心.png"
  8. type="image/x-icon"
  9. />
  10. <style>
  11. html,
  12. body {
  13. height: 100%;
  14. padding: 0;
  15. margin: 0;
  16. background: #000;
  17. }
  18. canvas {
  19. position: absolute;
  20. width: 100%;
  21. height: 100%;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <canvas id="pinkboard"></canvas>
  27. <script>
  28. var settings = {
  29. particles: {
  30. length: 500,
  31. duration: 2,
  32. velocity: 100,
  33. effect: -0.75,
  34. size: 32,
  35. },
  36. };
  37. (function () {
  38. var b = 0;
  39. var c = ["ms", "moz", "webkit", "o"];
  40. for (var a = 0; a < c.length && !window.requestAnimationFrame; ++a) {
  41. window.requestAnimationFrame = window[c[a] + "RequestAnimationFrame"];
  42. window.cancelAnimationFrame =
  43. window[c[a] + "CancelAnimationFrame"] ||
  44. window[c[a] + "CancelRequestAnimationFrame"];
  45. }
  46. if (!window.requestAnimationFrame) {
  47. window.requestAnimationFrame = function (h, e) {
  48. var d = new Date().getTime();
  49. var f = Math.max(0, 16 - (d - b));
  50. var g = window.setTimeout(function () {
  51. h(d + f);
  52. }, f);
  53. b = d + f;
  54. return g;
  55. };
  56. }
  57. if (!window.cancelAnimationFrame) {
  58. window.cancelAnimationFrame = function (d) {
  59. clearTimeout(d);
  60. };
  61. }
  62. })();
  63. var Point = (function () {
  64. function Point(x, y) {
  65. this.x = typeof x !== "undefined" ? x : 0;
  66. this.y = typeof y !== "undefined" ? y : 0;
  67. }
  68. Point.prototype.clone = function () {
  69. return new Point(this.x, this.y);
  70. };
  71. Point.prototype.length = function (length) {
  72. if (typeof length == "undefined")
  73. return Math.sqrt(this.x * this.x + this.y * this.y);
  74. this.normalize();
  75. this.x *= length;
  76. this.y *= length;
  77. return this;
  78. };
  79. Point.prototype.normalize = function () {
  80. var length = this.length();
  81. this.x /= length;
  82. this.y /= length;
  83. return this;
  84. };
  85. return Point;
  86. })();
  87. var Particle = (function () {
  88. function Particle() {
  89. this.position = new Point();
  90. this.velocity = new Point();
  91. this.acceleration = new Point();
  92. this.age = 0;
  93. }
  94. Particle.prototype.initialize = function (x, y, dx, dy) {
  95. this.position.x = x;
  96. this.position.y = y;
  97. this.velocity.x = dx;
  98. this.velocity.y = dy;
  99. this.acceleration.x = dx * settings.particles.effect;
  100. this.acceleration.y = dy * settings.particles.effect;
  101. this.age = 0;
  102. };
  103. Particle.prototype.update = function (deltaTime) {
  104. this.position.x += this.velocity.x * deltaTime;
  105. this.position.y += this.velocity.y * deltaTime;
  106. this.velocity.x += this.acceleration.x * deltaTime;
  107. this.velocity.y += this.acceleration.y * deltaTime;
  108. this.age += deltaTime;
  109. };
  110. Particle.prototype.draw = function (context, image) {
  111. function ease(t) {
  112. return --t * t * t + 1;
  113. }
  114. var size = image.width * ease(this.age / settings.particles.duration);
  115. context.globalAlpha = 1 - this.age / settings.particles.duration;
  116. context.drawImage(
  117. image,
  118. this.position.x - size / 2,
  119. this.position.y - size / 2,
  120. size,
  121. size
  122. );
  123. };
  124. return Particle;
  125. })();
  126. var ParticlePool = (function () {
  127. var particles,
  128. firstActive = 0,
  129. firstFree = 0,
  130. duration = settings.particles.duration;
  131. function ParticlePool(length) {
  132. // create and populate particle pool
  133. particles = new Array(length);
  134. for (var i = 0; i < particles.length; i++)
  135. particles[i] = new Particle();
  136. }
  137. ParticlePool.prototype.add = function (x, y, dx, dy) {
  138. particles[firstFree].initialize(x, y, dx, dy);
  139. // handle circular queue
  140. firstFree++;
  141. if (firstFree == particles.length) firstFree = 0;
  142. if (firstActive == firstFree) firstActive++;
  143. if (firstActive == particles.length) firstActive = 0;
  144. };
  145. ParticlePool.prototype.update = function (deltaTime) {
  146. var i;
  147. // update active particles
  148. if (firstActive < firstFree) {
  149. for (i = firstActive; i < firstFree; i++)
  150. particles[i].update(deltaTime);
  151. }
  152. if (firstFree < firstActive) {
  153. for (i = firstActive; i < particles.length; i++)
  154. particles[i].update(deltaTime);
  155. for (i = 0; i < firstFree; i++) particles[i].update(deltaTime);
  156. }
  157. // remove inactive particles
  158. while (
  159. particles[firstActive].age >= duration &&
  160. firstActive != firstFree
  161. ) {
  162. firstActive++;
  163. if (firstActive == particles.length) firstActive = 0;
  164. }
  165. };
  166. ParticlePool.prototype.draw = function (context, image) {
  167. // draw active particles
  168. if (firstActive < firstFree) {
  169. for (i = firstActive; i < firstFree; i++)
  170. particles[i].draw(context, image);
  171. }
  172. if (firstFree < firstActive) {
  173. for (i = firstActive; i < particles.length; i++)
  174. particles[i].draw(context, image);
  175. for (i = 0; i < firstFree; i++) particles[i].draw(context, image);
  176. }
  177. };
  178. return ParticlePool;
  179. })();
  180. (function (canvas) {
  181. var context = canvas.getContext("2d"),
  182. particles = new ParticlePool(settings.particles.length),
  183. particleRate =
  184. settings.particles.length / settings.particles.duration, // particles/sec
  185. time;
  186. // get point on heart with -PI <= t <= PI
  187. function pointOnHeart(t) {
  188. return new Point(
  189. 160 * Math.pow(Math.sin(t), 3),
  190. 130 * Math.cos(t) -
  191. 50 * Math.cos(2 * t) -
  192. 20 * Math.cos(3 * t) -
  193. 10 * Math.cos(4 * t) +
  194. 25
  195. );
  196. }
  197. // creating the particle image using a dummy canvas
  198. var image = (function () {
  199. var canvas = document.createElement("canvas"),
  200. context = canvas.getContext("2d");
  201. canvas.width = settings.particles.size;
  202. canvas.height = settings.particles.size;
  203. // helper function to create the path
  204. function to(t) {
  205. var point = pointOnHeart(t);
  206. point.x =
  207. settings.particles.size / 2 +
  208. (point.x * settings.particles.size) / 350;
  209. point.y =
  210. settings.particles.size / 2 -
  211. (point.y * settings.particles.size) / 350;
  212. return point;
  213. }
  214. // create the path
  215. context.beginPath();
  216. var t = -Math.PI;
  217. var point = to(t);
  218. context.moveTo(point.x, point.y);
  219. while (t < Math.PI) {
  220. t += 0.01; // baby steps!
  221. point = to(t);
  222. context.lineTo(point.x, point.y);
  223. }
  224. context.closePath();
  225. // create the fill
  226. context.fillStyle = "#ea80b0";
  227. context.fill();
  228. // create the image
  229. var image = new Image();
  230. image.src = canvas.toDataURL();
  231. return image;
  232. })();
  233. // render that thing!
  234. function render() {
  235. // next animation frame
  236. requestAnimationFrame(render);
  237. // update time
  238. var newTime = new Date().getTime() / 1000,
  239. deltaTime = newTime - (time || newTime);
  240. time = newTime;
  241. // clear canvas
  242. context.clearRect(0, 0, canvas.width, canvas.height);
  243. // create new particles
  244. var amount = particleRate * deltaTime;
  245. for (var i = 0; i < amount; i++) {
  246. var pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random());
  247. var dir = pos.clone().length(settings.particles.velocity);
  248. particles.add(
  249. canvas.width / 2 + pos.x,
  250. canvas.height / 2 - pos.y,
  251. dir.x,
  252. -dir.y
  253. );
  254. }
  255. // update and draw particles
  256. particles.update(deltaTime);
  257. particles.draw(context, image);
  258. }
  259. // handle (re-)sizing of the canvas
  260. function onResize() {
  261. canvas.width = canvas.clientWidth;
  262. canvas.height = canvas.clientHeight;
  263. }
  264. window.onresize = onResize;
  265. // delay rendering bootstrap
  266. setTimeout(function () {
  267. onResize();
  268. render();
  269. }, 10);
  270. })(document.getElementById("pinkboard"));
  271. </script>
  272. </body>
  273. </html>