neural-net.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. (function(){
  2. window.HPX = window.HPX || {};
  3. window.HPX['neural-net'] = function(el){
  4. const U = window.HPX._u;
  5. const k = U.canvas(el), ctx = k.ctx;
  6. const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
  7. const layers = [4,6,6,3];
  8. let nodes = [], edges = [], pulses = [];
  9. const layout = () => {
  10. nodes = [];
  11. const pad = 40;
  12. const cw = k.w - pad*2, ch = k.h - pad*2;
  13. for (let L=0; L<layers.length; L++){
  14. const x = pad + (cw * L / (layers.length-1));
  15. const n = layers[L];
  16. for (let i=0;i<n;i++){
  17. const y = pad + (ch * (i+0.5) / n);
  18. nodes.push({x,y,L,i});
  19. }
  20. }
  21. edges = [];
  22. for (let L=0; L<layers.length-1; L++){
  23. const a = nodes.filter(n=>n.L===L), b = nodes.filter(n=>n.L===L+1);
  24. for (const x of a) for (const y of b) edges.push([nodes.indexOf(x),nodes.indexOf(y)]);
  25. }
  26. };
  27. layout();
  28. let lw=k.w, lh=k.h, last=0;
  29. const stop = U.loop((t) => {
  30. if (k.w!==lw||k.h!==lh){ layout(); lw=k.w; lh=k.h; }
  31. ctx.clearRect(0,0,k.w,k.h);
  32. ctx.strokeStyle = 'rgba(160,160,200,0.22)'; ctx.lineWidth=1;
  33. for (const [i,j] of edges){
  34. const a=nodes[i], b=nodes[j];
  35. ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
  36. }
  37. if (t - last > 0.25){
  38. last = t;
  39. const starts = nodes.filter(n=>n.L===0);
  40. const s = starts[(Math.random()*starts.length)|0];
  41. pulses.push({node:s, L:0, t:0});
  42. }
  43. pulses = pulses.filter(p => p.L < layers.length-1);
  44. for (const p of pulses){
  45. p.t += 0.03;
  46. if (p.t >= 1){
  47. const next = nodes.filter(n=>n.L===p.L+1);
  48. p.node2 = next[(Math.random()*next.length)|0];
  49. if (!p._started){ p._started = true; }
  50. }
  51. }
  52. // animate progression
  53. for (const p of pulses){
  54. if (!p.target){
  55. const next = nodes.filter(n=>n.L===p.L+1);
  56. p.target = next[(Math.random()*next.length)|0];
  57. }
  58. p.t += 0.04;
  59. const a = p.node, b = p.target;
  60. const x = a.x + (b.x-a.x)*Math.min(1,p.t);
  61. const y = a.y + (b.y-a.y)*Math.min(1,p.t);
  62. ctx.fillStyle = ac2;
  63. ctx.beginPath(); ctx.arc(x,y,4,0,Math.PI*2); ctx.fill();
  64. if (p.t >= 1){ p.node = b; p.target=null; p.L++; p.t=0; }
  65. }
  66. for (const n of nodes){
  67. ctx.fillStyle = ac;
  68. ctx.beginPath(); ctx.arc(n.x,n.y,6,0,Math.PI*2); ctx.fill();
  69. ctx.strokeStyle = ac2; ctx.lineWidth=1.5;
  70. ctx.beginPath(); ctx.arc(n.x,n.y,8,0,Math.PI*2); ctx.stroke();
  71. }
  72. });
  73. return { stop(){ stop(); k.destroy(); } };
  74. };
  75. })();