sparkle-trail.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. (function(){
  2. window.HPX = window.HPX || {};
  3. window.HPX['sparkle-trail'] = function(el){
  4. const U = window.HPX._u;
  5. const k = U.canvas(el), ctx = k.ctx;
  6. k.c.style.pointerEvents = 'none';
  7. el.style.cursor = 'crosshair';
  8. const pal = U.palette(el);
  9. let sparks = [];
  10. const onMove = (e) => {
  11. const r = el.getBoundingClientRect();
  12. const x = e.clientX - r.left, y = e.clientY - r.top;
  13. for (let i=0;i<3;i++){
  14. sparks.push({
  15. x, y,
  16. vx: U.rand(-60,60), vy: U.rand(-80,20),
  17. life: 1, c: pal[(Math.random()*pal.length)|0],
  18. r: U.rand(1.5,3.5)
  19. });
  20. }
  21. };
  22. // auto-wiggle if no mouse moves
  23. let auto = true, autoT = 0;
  24. const onAny = () => { auto = false; };
  25. el.addEventListener('pointermove', onMove);
  26. el.addEventListener('pointerenter', onAny);
  27. const stop = U.loop(() => {
  28. ctx.fillStyle = 'rgba(0,0,0,0.15)';
  29. ctx.fillRect(0,0,k.w,k.h);
  30. if (auto){
  31. autoT += 0.04;
  32. const x = k.w/2 + Math.cos(autoT)*k.w*0.3;
  33. const y = k.h/2 + Math.sin(autoT*1.3)*k.h*0.3;
  34. for (let i=0;i<3;i++){
  35. sparks.push({
  36. x, y,
  37. vx: U.rand(-60,60), vy: U.rand(-80,20),
  38. life: 1, c: pal[(Math.random()*pal.length)|0],
  39. r: U.rand(1.5,3.5)
  40. });
  41. }
  42. }
  43. const dt = 1/60;
  44. sparks = sparks.filter(s => s.life > 0);
  45. for (const s of sparks){
  46. s.vy += 160*dt;
  47. s.x += s.vx*dt; s.y += s.vy*dt;
  48. s.life -= 0.018;
  49. ctx.globalAlpha = Math.max(0, s.life);
  50. ctx.fillStyle = s.c;
  51. ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,Math.PI*2); ctx.fill();
  52. }
  53. ctx.globalAlpha = 1;
  54. });
  55. return { stop(){
  56. el.removeEventListener('pointermove', onMove);
  57. el.removeEventListener('pointerenter', onAny);
  58. el.style.cursor = '';
  59. stop(); k.destroy();
  60. }};
  61. };
  62. })();