QueenOfGeckos

Cherry Blossom elements

Jun 7th, 2020
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.63 KB | None | 0 0
  1. ________________________JAVA_____________________
  2.  
  3.  
  4. var RENDERER = {
  5. INIT_CHERRY_BLOSSOM_COUNT : 30,
  6. MAX_ADDING_INTERVAL : 10,
  7. WATCH_INTERVAL : 300,
  8.  
  9. init : function(){
  10. this.setParameters();
  11. this.reconstructMethods();
  12. this.setup();
  13. this.bindEvent();
  14. this.render();
  15. },
  16. setParameters : function(){
  17. this.$window = $(window);
  18. this.$container = $('#jsi-cherry-container');
  19. this.$canvas = $('<canvas />');
  20. this.context = this.$canvas.appendTo(this.$container).get(0).getContext('2d');
  21. this.cherries = [];
  22. this.watchIds = [];
  23. },
  24. reconstructMethods : function(){
  25. this.watchWindowSize = this.watchWindowSize.bind(this);
  26. this.jdugeToStopResize = this.jdugeToStopResize.bind(this);
  27. this.render = this.render.bind(this);
  28. },
  29. setup : function(){
  30. this.cherries.length = 0;
  31. this.watchIds.length = 0;
  32. this.width = this.$container.width();
  33. this.height = this.$container.height();
  34. this.$canvas.attr({width : this.width, height : this.height});
  35. this.maxAddingInterval = Math.round(this.MAX_ADDING_INTERVAL * 1000 / this.width);
  36. this.addingInterval = this.maxAddingInterval;
  37. this.createCherries();
  38. },
  39. createCherries : function(){
  40. for(var i = 0, length = Math.round(this.INIT_CHERRY_BLOSSOM_COUNT * this.width / 1000); i < length; i++){
  41. this.cherries.push(new CHERRY_BLOSSOM(this, true));
  42. }
  43. },
  44. watchWindowSize : function(){
  45. this.clearTimer();
  46. this.tmpWidth = this.$window.width();
  47. this.tmpHeight = this.$window.height();
  48. this.watchIds.push(setTimeout(this.jdugeToStopResize, this.WATCH_INTERVAL));
  49. },
  50. clearTimer : function(){
  51. while(this.watchIds.length > 0){
  52. clearTimeout(this.watchIds.pop());
  53. }
  54. },
  55. jdugeToStopResize : function(){
  56. var width = this.$window.width(),
  57. height = this.$window.height(),
  58. stopped = (width == this.tmpWidth && height == this.tmpHeight);
  59.  
  60. this.tmpWidth = width;
  61. this.tmpHeight = height;
  62.  
  63. if(stopped){
  64. this.setup();
  65. }
  66. },
  67. bindEvent : function(){
  68. this.$window.on('resize', this.watchWindowSize);
  69. },
  70. render : function(){
  71. requestAnimationFrame(this.render);
  72. this.context.clearRect(0, 0, this.width, this.height);
  73.  
  74. this.cherries.sort(function(cherry1, cherry2){
  75. return cherry1.z - cherry2.z;
  76. });
  77. for(var i = this.cherries.length - 1; i >= 0; i--){
  78. if(!this.cherries[i].render(this.context)){
  79. this.cherries.splice(i, 1);
  80. }
  81. }
  82. if(--this.addingInterval == 0){
  83. this.addingInterval = this.maxAddingInterval;
  84. this.cherries.push(new CHERRY_BLOSSOM(this, false));
  85. }
  86. }
  87. };
  88. var CHERRY_BLOSSOM = function(renderer, isRandom){
  89. this.renderer = renderer;
  90. this.init(isRandom);
  91. };
  92. CHERRY_BLOSSOM.prototype = {
  93. FOCUS_POSITION : 300,
  94. FAR_LIMIT : 600,
  95. MAX_RIPPLE_COUNT : 100,
  96. RIPPLE_RADIUS : 100,
  97. SURFACE_RATE : 0.5,
  98. SINK_OFFSET : 20,
  99.  
  100. init : function(isRandom){
  101. this.x = this.getRandomValue(-this.renderer.width, this.renderer.width);
  102. this.y = isRandom ? this.getRandomValue(0, this.renderer.height) : this.renderer.height * 1.5;
  103. this.z = this.getRandomValue(0, this.FAR_LIMIT);
  104. this.vx = this.getRandomValue(-2, 2);
  105. this.vy = -2;
  106. this.theta = this.getRandomValue(0, Math.PI * 2);
  107. this.phi = this.getRandomValue(0, Math.PI * 2);
  108. this.psi = 0;
  109. this.dpsi = this.getRandomValue(Math.PI / 600, Math.PI / 300);
  110. this.opacity = 0;
  111. this.endTheta = false;
  112. this.endPhi = false;
  113. this.rippleCount = 0;
  114.  
  115. var axis = this.getAxis(),
  116. theta = this.theta + Math.ceil(-(this.y + this.renderer.height * this.SURFACE_RATE) / this.vy) * Math.PI / 500;
  117. theta %= Math.PI * 2;
  118.  
  119. this.offsetY = 40 * ((theta <= Math.PI / 2 || theta >= Math.PI * 3 / 2) ? -1 : 1);
  120. this.thresholdY = this.renderer.height / 2 + this.renderer.height * this.SURFACE_RATE * axis.rate;
  121. this.entityColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
  122. this.entityColor.addColorStop(0, 'hsl(330, 70%, ' + 50 * (0.3 + axis.rate) + '%)');
  123. this.entityColor.addColorStop(0.05, 'hsl(330, 40%,' + 55 * (0.3 + axis.rate) + '%)');
  124. this.entityColor.addColorStop(1, 'hsl(330, 20%, ' + 70 * (0.3 + axis.rate) + '%)');
  125. this.shadowColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
  126. this.shadowColor.addColorStop(0, 'hsl(330, 40%, ' + 30 * (0.3 + axis.rate) + '%)');
  127. this.shadowColor.addColorStop(0.05, 'hsl(330, 40%,' + 30 * (0.3 + axis.rate) + '%)');
  128. this.shadowColor.addColorStop(1, 'hsl(330, 20%, ' + 40 * (0.3 + axis.rate) + '%)');
  129. },
  130. getRandomValue : function(min, max){
  131. return min + (max - min) * Math.random();
  132. },
  133. getAxis : function(){
  134. var rate = this.FOCUS_POSITION / (this.z + this.FOCUS_POSITION),
  135. x = this.renderer.width / 2 + this.x * rate,
  136. y = this.renderer.height / 2 - this.y * rate;
  137. return {rate : rate, x : x, y : y};
  138. },
  139. renderCherry : function(context, axis){
  140. context.beginPath();
  141. context.moveTo(0, 40);
  142. context.bezierCurveTo(-60, 20, -10, -60, 0, -20);
  143. context.bezierCurveTo(10, -60, 60, 20, 0, 40);
  144. context.fill();
  145.  
  146. for(var i = -4; i < 4; i++){
  147. context.beginPath();
  148. context.moveTo(0, 40);
  149. context.quadraticCurveTo(i * 12, 10, i * 4, -24 + Math.abs(i) * 2);
  150. context.stroke();
  151. }
  152. },
  153. render : function(context){
  154. var axis = this.getAxis();
  155.  
  156. if(axis.y == this.thresholdY && this.rippleCount < this.MAX_RIPPLE_COUNT){
  157. context.save();
  158. context.lineWidth = 2;
  159. context.strokeStyle = 'hsla(0, 0%, 100%, ' + (this.MAX_RIPPLE_COUNT - this.rippleCount) / this.MAX_RIPPLE_COUNT + ')';
  160. context.translate(axis.x + this.offsetY * axis.rate * (this.theta <= Math.PI ? -1 : 1), axis.y);
  161. context.scale(1, 0.3);
  162. context.beginPath();
  163. context.arc(0, 0, this.rippleCount / this.MAX_RIPPLE_COUNT * this.RIPPLE_RADIUS * axis.rate, 0, Math.PI * 2, false);
  164. context.stroke();
  165. context.restore();
  166. this.rippleCount++;
  167. }
  168. if(axis.y < this.thresholdY || (!this.endTheta || !this.endPhi)){
  169. if(this.y <= 0){
  170. this.opacity = Math.min(this.opacity + 0.01, 1);
  171. }
  172. context.save();
  173. context.globalAlpha = this.opacity;
  174. context.fillStyle = this.shadowColor;
  175. context.strokeStyle = 'hsl(330, 30%,' + 40 * (0.3 + axis.rate) + '%)';
  176. context.translate(axis.x, Math.max(axis.y, this.thresholdY + this.thresholdY - axis.y));
  177. context.rotate(Math.PI - this.theta);
  178. context.scale(axis.rate * -Math.sin(this.phi), axis.rate);
  179. context.translate(0, this.offsetY);
  180. this.renderCherry(context, axis);
  181. context.restore();
  182. }
  183. context.save();
  184. context.fillStyle = this.entityColor;
  185. context.strokeStyle = 'hsl(330, 40%,' + 70 * (0.3 + axis.rate) + '%)';
  186. context.translate(axis.x, axis.y + Math.abs(this.SINK_OFFSET * Math.sin(this.psi) * axis.rate));
  187. context.rotate(this.theta);
  188. context.scale(axis.rate * Math.sin(this.phi), axis.rate);
  189. context.translate(0, this.offsetY);
  190. this.renderCherry(context, axis);
  191. context.restore();
  192.  
  193. if(this.y <= -this.renderer.height / 4){
  194. if(!this.endTheta){
  195. for(var theta = Math.PI / 2, end = Math.PI * 3 / 2; theta <= end; theta += Math.PI){
  196. if(this.theta < theta && this.theta + Math.PI / 200 > theta){
  197. this.theta = theta;
  198. this.endTheta = true;
  199. break;
  200. }
  201. }
  202. }
  203. if(!this.endPhi){
  204. for(var phi = Math.PI / 8, end = Math.PI * 7 / 8; phi <= end; phi += Math.PI * 3 / 4){
  205. if(this.phi < phi && this.phi + Math.PI / 200 > phi){
  206. this.phi = Math.PI / 8;
  207. this.endPhi = true;
  208. break;
  209. }
  210. }
  211. }
  212. }
  213. if(!this.endTheta){
  214. if(axis.y == this.thresholdY){
  215. this.theta += Math.PI / 200 * ((this.theta < Math.PI / 2 || (this.theta >= Math.PI && this.theta < Math.PI * 3 / 2)) ? 1 : -1);
  216. }else{
  217. this.theta += Math.PI / 500;
  218. }
  219. this.theta %= Math.PI * 2;
  220. }
  221. if(this.endPhi){
  222. if(this.rippleCount == this.MAX_RIPPLE_COUNT){
  223. this.psi += this.dpsi;
  224. this.psi %= Math.PI * 2;
  225. }
  226. }else{
  227. this.phi += Math.PI / ((axis.y == this.thresholdY) ? 200 : 500);
  228. this.phi %= Math.PI;
  229. }
  230. if(this.y <= -this.renderer.height * this.SURFACE_RATE){
  231. this.x += 2;
  232. this.y = -this.renderer.height * this.SURFACE_RATE;
  233. }else{
  234. this.x += this.vx;
  235. this.y += this.vy;
  236. }
  237. return this.z > -this.FOCUS_POSITION && this.z < this.FAR_LIMIT && this.x < this.renderer.width * 1.5;
  238. }
  239. };
  240. $(function(){
  241. RENDERER.init();
  242. });
  243.  
  244. _________________{CSS this is separate from the Body css portion}____________
  245.  
  246.  
  247.  
  248.  
  249. .container{
  250. background-color: #transparent;
  251. width: 100%;
  252. height: 100%;
  253. margin: 0;
  254. padding: 0;
  255. background-color: transparent;
  256. }
  257.  
  258. ____________________HTML(make sure this goes at the very top)_____________________________
  259.  
  260. <div id="jsi-cherry-container" class="container"></div>
Add Comment
Please, Sign In to add comment