הפרט הקטן שגורם למבקרים לזוז עם העכבר רק כדי לראות מה קורה. עובד על כל תמונה: מודדים את מרכזי האישונים באחוזים, והרכיב מצייר אישונים חדשים מעליהם. עיניים עוקבות הוא רכיב מתוך רכיבים של כליקס. מה שמורידים הוא רכיב שלם, גם כ-HTML עצמאי וגם כרכיב React. אין ספרייה חיצונית, אין שלב בנייה, ואם כליקס ייעלם מחר הקוד ימשיך לעבוד.
רכיב · ריחוף · בלי ספריות · מסקוט
<!-- עיניים עוקבות — החליפו את כתובת התמונה ומדדו את מרכזי האישונים -->
<div class="klix-eyes">
<img src="/images/mascot.png" alt="">
</div>
<style>
.klix-eyes{position:relative;display:inline-block;max-width:20rem}
.klix-eyes img{display:block;width:100%}
.klix-eyes .pupil{position:absolute;border-radius:999px;pointer-events:none;
aspect-ratio:1;transform:translate(-50%,-50%);transition:transform .1s ease-out}
.klix-eyes .pupil i{position:absolute;left:22%;top:18%;width:26%;height:26%;
border-radius:999px;background:rgba(255,255,255,.9)}
</style>
<script>
(function () {
// ═══ ערכו כאן ═══
// מרכזי האישונים באחוזים מרוחב וגובה התמונה. חשוב למדוד מהקובץ עצמו
// ולא בעין — סטייה של אחוז אחד נראית כמו פזילה.
var EYES = [{ x: 38, y: 47.7 }, { x: 62, y: 47.7 }];
var PUPIL = 8; // קוטר האישון, באחוזים מרוחב התמונה
var REACH = 2.2; // כמה הוא זז, באותם אחוזים
var COLOR = '#14212a';
// ═════════════════
var box = document.querySelector('.klix-eyes');
if (!box) return;
var pupils = EYES.map(function (eye) {
var el = document.createElement('span');
el.className = 'pupil';
el.setAttribute('aria-hidden', 'true');
el.style.width = PUPIL + '%';
el.style.left = eye.x + '%';
el.style.top = eye.y + '%';
el.style.background = COLOR;
el.appendChild(document.createElement('i'));
box.appendChild(el);
return el;
});
// במכשירי מגע אין סמן, והאישונים פשוט נחים במרכז
if (window.matchMedia('(pointer: coarse)').matches) return;
var pending = false, mx = 0, my = 0;
function apply() {
pending = false;
var r = box.getBoundingClientRect();
if (!r.width) return;
for (var i = 0; i < EYES.length; i++) {
var cx = r.left + (EYES[i].x / 100) * r.width;
var cy = r.top + (EYES[i].y / 100) * r.height;
var dx = mx - cx, dy = my - cy;
var dist = Math.hypot(dx, dy) || 1;
// רוויה: ככל שהסמן רחוק התזוזה מתקרבת ל-REACH, בלי קפיצה כשהוא צמוד
var pull = Math.min(1, dist / 260);
var move = (REACH / 100) * r.width * pull;
pupils[i].style.transform = 'translate(calc(-50% + ' + ((dx / dist) * move) +
'px), calc(-50% + ' + ((dy / dist) * move) + 'px))';
}
}
window.addEventListener('pointermove', function (e) {
mx = e.clientX; my = e.clientY;
if (!pending) { pending = true; requestAnimationFrame(apply); }
}, { passive: true });
})();
</script>