@ifed/hook
Version:
107 lines (106 loc) • 3.41 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = require("react");
var _easingFunctions = _interopRequireDefault(require("./easingFunctions"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const useAnimateNumber = ({
number = 0,
durationInMs = 4000,
easingFunctionName = 'easeOutExpo',
setInitialValue = false
}) => {
const decimalPlaces = String(number).split('.')?.[1]?.length || 0;
const [data, setData] = (0, _react.useState)({
currentNumber: 0,
originalNumber: setInitialValue ? number : 0,
step: 0,
isGoingUp: false,
isAnimating: false
});
const requestRef = (0, _react.useRef)();
const mountedRef = (0, _react.useRef)(true);
const previousTimeRef = (0, _react.useRef)();
const animate = (0, _react.useCallback)(time => {
if (!mountedRef.current) return;
if (previousTimeRef.current === undefined) {
previousTimeRef.current = time;
requestRef.current = requestAnimationFrame(animate);
return;
}
const reset = () => {
setData({
currentNumber: number,
originalNumber: number,
step: 0,
isGoingUp: false,
isAnimating: false
});
previousTimeRef.current = undefined;
if (requestRef.current) cancelAnimationFrame(requestRef.current);
requestRef.current = undefined;
};
if (typeof number !== 'number') {
try {
number = parseFloat(number);
} catch (e) {
console.error('useAnimateNumber: number is not a number');
reset();
return;
}
}
if (number === data.currentNumber) {
reset();
return;
}
const deltaTime = time - previousTimeRef.current;
if (deltaTime >= durationInMs) {
reset();
return;
}
let easingFunction = _easingFunctions.default.easeOutExpo;
if (easingFunctionName && _easingFunctions.default[easingFunctionName]) {
easingFunction = _easingFunctions.default[easingFunctionName];
}
const progress = deltaTime / durationInMs;
const percentageOfTargetValue = easingFunction(progress);
let currentValue = percentageOfTargetValue * number;
setData(previousData => {
const isGoingUp = number > previousData.originalNumber;
if (!isGoingUp) {
currentValue = (1 - percentageOfTargetValue) * previousData.originalNumber + number;
}
if (currentValue !== 0) {
currentValue = parseFloat(currentValue.toFixed(decimalPlaces));
}
if (isGoingUp && currentValue > number) {
currentValue = number;
}
if (!isGoingUp && currentValue < number) {
currentValue = number;
}
return {
...previousData,
currentNumber: currentValue,
isGoingUp,
isAnimating: true
};
});
requestRef.current = window.requestAnimationFrame(animate);
}, [number, durationInMs, decimalPlaces, easingFunctionName]);
(0, _react.useEffect)(() => {
requestRef.current = window.requestAnimationFrame(animate);
return () => {
if (requestRef.current) cancelAnimationFrame(requestRef.current);
};
}, [number, animate]);
return {
number: data.currentNumber,
isGoingUp: data.isGoingUp,
isAnimating: data.isAnimating
};
};
var _default = useAnimateNumber;
exports.default = _default;