|
|
|
|
@@ -25,34 +25,45 @@ function MagneticRing({
|
|
|
|
|
// Only run on client with mouse
|
|
|
|
|
if (window.matchMedia("(pointer: coarse)").matches) return;
|
|
|
|
|
|
|
|
|
|
let ticking = false;
|
|
|
|
|
|
|
|
|
|
const handleMouseMove = (e: MouseEvent) => {
|
|
|
|
|
if (!ref.current) return;
|
|
|
|
|
const rect = ref.current.getBoundingClientRect();
|
|
|
|
|
const centerX = rect.left + rect.width / 2;
|
|
|
|
|
const centerY = rect.top + rect.height / 2;
|
|
|
|
|
|
|
|
|
|
if (!ticking) {
|
|
|
|
|
window.requestAnimationFrame(() => {
|
|
|
|
|
if (!ref.current) {
|
|
|
|
|
ticking = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const rect = ref.current.getBoundingClientRect();
|
|
|
|
|
const centerX = rect.left + rect.width / 2;
|
|
|
|
|
const centerY = rect.top + rect.height / 2;
|
|
|
|
|
|
|
|
|
|
const distX = e.clientX - centerX;
|
|
|
|
|
const distY = e.clientY - centerY;
|
|
|
|
|
const distance = Math.sqrt(distX * Math.pow(distX, 2) + Math.pow(distY, 2)); // Fix: correct pythagoras
|
|
|
|
|
const distX = e.clientX - centerX;
|
|
|
|
|
const distY = e.clientY - centerY;
|
|
|
|
|
const actualDistance = Math.sqrt(distX * distX + distY * distY);
|
|
|
|
|
|
|
|
|
|
// Calculate actual distance correctly
|
|
|
|
|
const actualDistance = Math.sqrt(distX * distX + distY * distY);
|
|
|
|
|
|
|
|
|
|
if (actualDistance < pullRadius) {
|
|
|
|
|
// Exponential falloff for natural magnetic feel
|
|
|
|
|
const pullFactor = Math.pow(1 - (actualDistance / pullRadius), 2);
|
|
|
|
|
|
|
|
|
|
// Target offset (fraction of the distance based on strength)
|
|
|
|
|
x.set(distX * pullFactor * (pullStrength / 100));
|
|
|
|
|
y.set(distY * pullFactor * (pullStrength / 100));
|
|
|
|
|
} else {
|
|
|
|
|
// Return to origin smoothly
|
|
|
|
|
x.set(0);
|
|
|
|
|
y.set(0);
|
|
|
|
|
if (actualDistance < pullRadius) {
|
|
|
|
|
// Exponential falloff for natural magnetic feel
|
|
|
|
|
const pullFactor = Math.pow(1 - (actualDistance / pullRadius), 2);
|
|
|
|
|
|
|
|
|
|
// Target offset (fraction of the distance based on strength)
|
|
|
|
|
x.set(distX * pullFactor * (pullStrength / 100));
|
|
|
|
|
y.set(distY * pullFactor * (pullStrength / 100));
|
|
|
|
|
} else {
|
|
|
|
|
// Return to origin smoothly
|
|
|
|
|
x.set(0);
|
|
|
|
|
y.set(0);
|
|
|
|
|
}
|
|
|
|
|
ticking = false;
|
|
|
|
|
});
|
|
|
|
|
ticking = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.addEventListener('mousemove', handleMouseMove);
|
|
|
|
|
window.addEventListener('mousemove', handleMouseMove, { passive: true });
|
|
|
|
|
return () => window.removeEventListener('mousemove', handleMouseMove);
|
|
|
|
|
}, [x, y, pullRadius, pullStrength]);
|
|
|
|
|
|
|
|
|
|
|