JavaScript.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. 
  2. // min and max radius, radius threshold and percentage of filled circles
  3. var radMin = 5,
  4. radMax = 125,
  5. filledCircle = 60, //percentage of filled circles
  6. concentricCircle = 30, //percentage of concentric circles
  7. radThreshold = 25; //IFF special, over this radius concentric, otherwise filled
  8. //min and max speed to move
  9. var speedMin = 0.3,
  10. speedMax = 2.5;
  11. //max reachable opacity for every circle and blur effect
  12. var maxOpacity = 0.6;
  13. //default palette choice
  14. var colors = ['52,168,83', '117,95,147', '199,108,23', '194,62,55', '0,172,212', '120,120,120'],
  15. bgColors = ['52,168,83', '117,95,147', '199,108,23', '194,62,55', '0,172,212', '120,120,120'],
  16. circleBorder = 10,
  17. backgroundLine = bgColors[0];
  18. var backgroundMlt = 0.85;
  19. //min distance for links
  20. var linkDist = Math.min(canvas.width, canvas.height) / 2.4,
  21. lineBorder = 2.5;
  22. //most importantly: number of overall circles and arrays containing them
  23. var maxCircles = 12,
  24. points = [],
  25. pointsBack = [];
  26. //populating the screen
  27. for (var i = 0; i < maxCircles * 2; i++) points.push(new Circle());
  28. for (var i = 0; i < maxCircles; i++) pointsBack.push(new Circle(true));
  29. //experimental vars
  30. var circleExp = 1,
  31. circleExpMax = 1.003,
  32. circleExpMin = 0.997,
  33. circleExpSp = 0.00004,
  34. circlePulse = false;
  35. //circle class
  36. function Circle(background) {
  37. //if background, it has different rules
  38. this.background = (background || false);
  39. this.x = randRange(-canvas.width / 2, canvas.width / 2);
  40. this.y = randRange(-canvas.height / 2, canvas.height / 2);
  41. this.radius = background ? hyperRange(radMin, radMax) * backgroundMlt : hyperRange(radMin, radMax);
  42. this.filled = this.radius < radThreshold ? (randint(0, 100) > filledCircle ? false : 'full') : (randint(0, 100) > concentricCircle ? false : 'concentric');
  43. this.color = background ? bgColors[randint(0, bgColors.length - 1)] : colors[randint(0, colors.length - 1)];
  44. this.borderColor = background ? bgColors[randint(0, bgColors.length - 1)] : colors[randint(0, colors.length - 1)];
  45. this.opacity = 0.05;
  46. this.speed = (background ? randRange(speedMin, speedMax) / backgroundMlt : randRange(speedMin, speedMax)); // * (radMin / this.radius);
  47. this.speedAngle = Math.random() * 2 * Math.PI;
  48. this.speedx = Math.cos(this.speedAngle) * this.speed;
  49. this.speedy = Math.sin(this.speedAngle) * this.speed;
  50. var spacex = Math.abs((this.x - (this.speedx < 0 ? -1 : 1) * (canvas.width / 2 + this.radius)) / this.speedx),
  51. spacey = Math.abs((this.y - (this.speedy < 0 ? -1 : 1) * (canvas.height / 2 + this.radius)) / this.speedy);
  52. this.ttl = Math.min(spacex, spacey);
  53. };
  54. Circle.prototype.init = function () {
  55. Circle.call(this, this.background);
  56. }
  57. //support functions
  58. //generate random int a<=x<=b
  59. function randint(a, b) {
  60. return Math.floor(Math.random() * (b - a + 1) + a);
  61. }
  62. //generate random float
  63. function randRange(a, b) {
  64. return Math.random() * (b - a) + a;
  65. }
  66. //generate random float more likely to be close to a
  67. function hyperRange(a, b) {
  68. return Math.random() * Math.random() * Math.random() * (b - a) + a;
  69. }
  70. //rendering function
  71. function drawCircle(ctx, circle) {
  72. //circle.radius *= circleExp;
  73. var radius = circle.background ? circle.radius *= circleExp : circle.radius /= circleExp;
  74. ctx.beginPath();
  75. ctx.arc(circle.x, circle.y, radius * circleExp, 0, 2 * Math.PI, false);
  76. ctx.lineWidth = Math.max(1, circleBorder * (radMin - circle.radius) / (radMin - radMax));
  77. ctx.strokeStyle = ['rgba(', circle.borderColor, ',', circle.opacity, ')'].join('');
  78. if (circle.filled == 'full') {
  79. ctx.fillStyle = ['rgba(', circle.borderColor, ',', circle.background ? circle.opacity * 0.8 : circle.opacity, ')'].join('');
  80. ctx.fill();
  81. ctx.lineWidth = 0;
  82. ctx.strokeStyle = ['rgba(', circle.borderColor, ',', 0, ')'].join('');
  83. }
  84. ctx.stroke();
  85. if (circle.filled == 'concentric') {
  86. ctx.beginPath();
  87. ctx.arc(circle.x, circle.y, radius / 2, 0, 2 * Math.PI, false);
  88. ctx.lineWidth = Math.max(1, circleBorder * (radMin - circle.radius) / (radMin - radMax));
  89. ctx.strokeStyle = ['rgba(', circle.color, ',', circle.opacity, ')'].join('');
  90. ctx.stroke();
  91. }
  92. circle.x += circle.speedx;
  93. circle.y += circle.speedy;
  94. if (circle.opacity < (circle.background ? maxOpacity : 1)) circle.opacity += 0.01;
  95. circle.ttl--;
  96. }
  97. //initializing function
  98. function init() {
  99. window.requestAnimationFrame(draw);
  100. }
  101. //rendering function
  102. function draw() {
  103. if (circlePulse) {
  104. if (circleExp < circleExpMin || circleExp > circleExpMax) circleExpSp *= -1;
  105. circleExp += circleExpSp;
  106. }
  107. var ctxfr = document.getElementById('canvas').getContext('2d');
  108. var ctxbg = document.getElementById('canvasbg').getContext('2d');
  109. ctxfr.globalCompositeOperation = 'destination-over';
  110. ctxfr.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
  111. ctxbg.globalCompositeOperation = 'destination-over';
  112. ctxbg.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
  113. ctxfr.save();
  114. ctxfr.translate(canvas.width / 2, canvas.height / 2);
  115. ctxbg.save();
  116. ctxbg.translate(canvas.width / 2, canvas.height / 2);
  117. //function to render each single circle, its connections and to manage its out of boundaries replacement
  118. function renderPoints(ctx, arr) {
  119. for (var i = 0; i < arr.length; i++) {
  120. var circle = arr[i];
  121. //checking if out of boundaries
  122. if (circle.ttl < 0) { }
  123. var xEscape = canvas.width / 2 + circle.radius,
  124. yEscape = canvas.height / 2 + circle.radius;
  125. if (circle.ttl < -20) arr[i].init(arr[i].background);
  126. //if (Math.abs(circle.y) > yEscape || Math.abs(circle.x) > xEscape) arr[i].init(arr[i].background);
  127. drawCircle(ctx, circle);
  128. }
  129. for (var i = 0; i < arr.length - 1; i++) {
  130. for (var j = i + 1; j < arr.length; j++) {
  131. var deltax = arr[i].x - arr[j].x;
  132. var deltay = arr[i].y - arr[j].y;
  133. var dist = Math.pow(Math.pow(deltax, 2) + Math.pow(deltay, 2), 0.5);
  134. //if the circles are overlapping, no laser connecting them
  135. if (dist <= arr[i].radius + arr[j].radius) continue;
  136. //otherwise we connect them only if the dist is < linkDist
  137. if (dist < linkDist) {
  138. var xi = (arr[i].x < arr[j].x ? 1 : -1) * Math.abs(arr[i].radius * deltax / dist);
  139. var yi = (arr[i].y < arr[j].y ? 1 : -1) * Math.abs(arr[i].radius * deltay / dist);
  140. var xj = (arr[i].x < arr[j].x ? -1 : 1) * Math.abs(arr[j].radius * deltax / dist);
  141. var yj = (arr[i].y < arr[j].y ? -1 : 1) * Math.abs(arr[j].radius * deltay / dist);
  142. ctx.beginPath();
  143. ctx.moveTo(arr[i].x + xi, arr[i].y + yi);
  144. ctx.lineTo(arr[j].x + xj, arr[j].y + yj);
  145. var samecolor = arr[i].color == arr[j].color;
  146. ctx.strokeStyle = ["rgba(", arr[i].borderColor, ",", Math.min(arr[i].opacity, arr[j].opacity) * ((linkDist - dist) / linkDist), ")"].join("");
  147. ctx.lineWidth = (arr[i].background ? lineBorder * backgroundMlt : lineBorder) * ((linkDist - dist) / linkDist); //*((linkDist-dist)/linkDist);
  148. ctx.stroke();
  149. }
  150. }
  151. }
  152. }
  153. var startTime = Date.now();
  154. renderPoints(ctxfr, points);
  155. renderPoints(ctxbg, pointsBack);
  156. deltaT = Date.now() - startTime;
  157. ctxfr.restore();
  158. ctxbg.restore();
  159. window.requestAnimationFrame(draw);
  160. }
  161. $(function () {
  162. init();
  163. });
  164. /*Credits and aknowledgements:
  165. Original Idea and Design by Luca Luzzatti
  166. Optimizing tips from Benjamin K?stner
  167. General tips from Salvatore Previti*/