feat: performance improvements

This commit is contained in:
2026-04-06 20:16:46 +02:00
parent d7e9788f99
commit 2994735f3b
4 changed files with 78 additions and 35 deletions

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef, useCallback } from "react";
interface LazyEyesOptions {
/** Reference point the eyes "live" at (viewport coords). Eyes look away from this toward the mouse. */
@@ -14,8 +14,8 @@ interface LazyEyesOptions {
}
/**
* Returns a smoothly-interpolated { x, y } offset for positioning irises
* that lazily track the mouse cursor relative to an anchor point.
* Returns a register function to attach iris elements for direct DOM updates.
* No React state is set per frame — transforms are applied directly.
*
* Movement model:
* - Small mouse moves → slow, lazy drift (ease)
@@ -29,10 +29,23 @@ export function useLazyEyes({
saccadeThreshold = 0.8,
saccadeEase = 0.35,
}: LazyEyesOptions) {
const [offset, setOffset] = useState({ x: 0, y: 0 });
const targetRef = useRef({ x: 0, y: 0 });
const currentRef = useRef({ x: 0, y: 0 });
const velocityRef = useRef({ x: 0, y: 0 });
const irisesRef = useRef<Set<HTMLElement>>(new Set());
const offsetRef = useRef({ x: 0, y: 0 });
const registerIris = useCallback((el: HTMLElement | null) => {
if (el) {
irisesRef.current.add(el);
}
}, []);
const unregisterIris = useCallback((el: HTMLElement | null) => {
if (el) {
irisesRef.current.delete(el);
}
}, []);
useEffect(() => {
const onMouseMove = (e: MouseEvent) => {
@@ -55,27 +68,30 @@ export function useLazyEyes({
const et = targetRef.current;
const vel = velocityRef.current;
// Distance to target
const dx = et.x - ec.x;
const dy = et.y - ec.y;
const dist = Math.sqrt(dx * dx + dy * dy);
// Saccade: snap fast when target jumps significantly
const e_ = dist > saccadeThreshold ? saccadeEase : ease;
// Apply eased movement
vel.x = vel.x * 0.6 + dx * e_ * 0.4;
vel.y = vel.y * 0.6 + dy * e_ * 0.4;
ec.x += vel.x;
ec.y += vel.y;
// Micro-drift: tiny organic tremor when nearly still
if (dist < 0.1) {
ec.x += (Math.random() - 0.5) * 0.02;
ec.y += (Math.random() - 0.5) * 0.02;
}
setOffset({ x: ec.x, y: ec.y });
offsetRef.current.x = ec.x;
offsetRef.current.y = ec.y;
// Direct DOM updates — no React re-render
for (const iris of irisesRef.current) {
iris.style.transform = `translate(${ec.x}px, ${ec.y}px)`;
}
raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
@@ -86,5 +102,5 @@ export function useLazyEyes({
};
}, [anchorRef, maxShift, ease, saccadeThreshold, saccadeEase]);
return offset;
return { offsetRef, registerIris, unregisterIris };
}