זוהר עוקב

נותן עומק לסקשן כהה בלי להוסיף תמונה או וידאו. המיקום נכתב למשתנה CSS ולא ל-state, ולכן תזוזת עכבר לא מרנדרת את הדף מחדש. זוהר עוקב הוא רכיב מתוך רכיבים של כליקס. מה שמורידים הוא רכיב שלם, גם כ-HTML עצמאי וגם כרכיב React. אין ספרייה חיצונית, אין שלב בנייה, ואם כליקס ייעלם מחר הקוד ימשיך לעבוד.

רכיב · ריחוף · בלי ספריות · רקע

<!-- זוהר עוקב — הוסיפו את המחלקה klix-spotlight לכל אלמנט -->
<style>
  .klix-spotlight{position:relative;overflow:hidden}
  .klix-spotlight::before{
    content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
    background:radial-gradient(var(--klix-spot-size,460px) circle at var(--sx,-9999px) var(--sy,-9999px),
               var(--klix-spot-color,rgba(200,164,21,.22)), transparent 65%);
  }
  .klix-spotlight > *{position:relative;z-index:1}
</style>

<script>
(function () {
  // במגע אין ריחוף, ו-pointerleave לא אמין — הזוהר היה נתקע במקום
  if (!window.matchMedia('(hover: hover)').matches) return;

  document.querySelectorAll('.klix-spotlight').forEach(function (el) {
    var tx = -9999, ty = -9999, cx = -9999, cy = -9999;
    var raf = 0, running = false;

    // החלקה ב-lerp. הלולאה נרגעת מעצמה כשהזוהר מגיע ליעד,
    // כדי שלא יישאר rAF שרץ לנצח על דף שאיש לא נוגע בו.
    function tick() {
      cx += (tx - cx) * 0.18;
      cy += (ty - cy) * 0.18;
      el.style.setProperty('--sx', cx + 'px');
      el.style.setProperty('--sy', cy + 'px');
      if (Math.abs(tx - cx) < 0.5 && Math.abs(ty - cy) < 0.5) { running = false; return; }
      raf = requestAnimationFrame(tick);
    }
    function ensure() { if (!running) { running = true; raf = requestAnimationFrame(tick); } }

    el.addEventListener('pointermove', function (e) {
      var r = el.getBoundingClientRect();
      tx = e.clientX - r.left;
      ty = e.clientY - r.top;
      ensure();
    });
    el.addEventListener('pointerleave', function () { tx = -9999; ty = -9999; ensure(); });
  });
})();
</script>