Skip to content

Commit

Permalink
split the useSmoothAnimation hook
Browse files Browse the repository at this point in the history
  • Loading branch information
yhattav committed Dec 2, 2024
1 parent b06d0b7 commit d64405f
Showing 1 changed file with 54 additions and 24 deletions.
78 changes: 54 additions & 24 deletions src/hooks/useSmoothAnimation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useCallback } from 'react';
import { Position, TargetPosition } from '../types';

const SMOOTHING_THRESHOLD = 0.1;
Expand All @@ -9,37 +9,45 @@ export function useSmoothAnimation(
smoothFactor: number,
setPosition: React.Dispatch<React.SetStateAction<Position>>
) {
useEffect(() => {
if (position.x === null || position.y === null) return;
if (position.x === targetPosition.x && position.y === targetPosition.y) {
return;
}
// Memoize the smoothing calculation
const calculateNewPosition = useCallback(
(currentPosition: Position) => {
if (currentPosition.x === null || currentPosition.y === null) {
return currentPosition;
}

let animationFrameId: number;
const dx = targetPosition.x - currentPosition.x;
const dy = targetPosition.y - currentPosition.y;

if (smoothFactor === 1) {
setPosition(targetPosition);
return;
}
if (
Math.abs(dx) < SMOOTHING_THRESHOLD &&
Math.abs(dy) < SMOOTHING_THRESHOLD
) {
return currentPosition;
}

return {
x: currentPosition.x + dx / smoothFactor,
y: currentPosition.y + dy / smoothFactor,
};
},
[targetPosition.x, targetPosition.y, smoothFactor]
);

// Memoize the animation frame callback
const animate = useCallback(() => {
let animationFrameId: number;

const smoothing = () => {
setPosition((prev) => {
if (prev.x === null || prev.y === null) return prev;

const dx = targetPosition.x - prev.x;
const dy = targetPosition.y - prev.y;
const newPosition = calculateNewPosition(prev);

if (
Math.abs(dx) < SMOOTHING_THRESHOLD &&
Math.abs(dy) < SMOOTHING_THRESHOLD
) {
// Only trigger update if position actually changed
if (newPosition.x === prev.x && newPosition.y === prev.y) {
return prev;
}

return {
x: prev.x + dx / smoothFactor,
y: prev.y + dy / smoothFactor,
};
return newPosition;
});

animationFrameId = requestAnimationFrame(smoothing);
Expand All @@ -52,7 +60,29 @@ export function useSmoothAnimation(
cancelAnimationFrame(animationFrameId);
}
};
}, [position.x, position.y, targetPosition, smoothFactor, setPosition]);
}, [calculateNewPosition, setPosition]);

useEffect(() => {
// If smoothFactor is 1, just set position directly
if (smoothFactor === 1) {
setPosition(targetPosition);
return;
}

// Skip animation if position is null
if (position.x === null || position.y === null) {
return;
}

return animate();
}, [
smoothFactor,
position.x,
position.y,
targetPosition,
animate,
setPosition,
]);

return null;
}

0 comments on commit d64405f

Please sign in to comment.