UNPKG

@anton.bobrov/react-vevet-hooks

Version:

A collection of custom React hooks designed to seamlessly integrate with the `Vevet` library

80 lines 3.04 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; import { objectKeys, useEvent } from '@anton.bobrov/react-hooks'; import { useCallback, useRef } from 'react'; import { lerp } from 'vevet'; import { useAnimationFrame } from './useAnimationFrame'; /** * Custom React hook that synchronizes animation frame data using linear interpolation. * * This hook allows you to smoothly animate properties by specifying their initial values. * It uses linear interpolation to transition between current and target values. * The animation frame will automatically stop once all values reach their targets. * * @example * const { set } = useAnimationFrameSync({ * data: { x: 0, y: 0 }, * onUpdate: ({ x, y }) => console.log(x, y), * }); * * set('x', 1); * set('y', 0.5); * set('y', 0.5, true); // instant change */ export function useAnimationFrameSync(_a) { var initialData = _a.data, onUpdateProp = _a.onUpdate, onSetProp = _a.onSet, _b = _a.ease, easeProp = _b === void 0 ? 0.1 : _b; var onUpdate = useEvent(onUpdateProp); var onSet = useEvent(onSetProp); var dataRef = useRef({ moment: __assign({}, initialData), target: __assign({}, initialData), }); var props = objectKeys(initialData); var _c = dataRef.current, moment = _c.moment, target = _c.target; var render = useEvent(function (ease) { props.forEach(function (prop) { // @ts-ignore moment[prop] = lerp(moment[prop], target[prop], ease); }); onUpdate(moment); }); var _d = useAnimationFrame({ onFrame: function (_a) { var fpsMultiplier = _a.fpsMultiplier; var ease = easeProp * fpsMultiplier; render(ease); var undone = props.filter(function (prop) { return moment[prop] !== target[prop]; }); var isInterpolated = undone.length === 0; if (isInterpolated) { pause(); } }, }), play = _d.play, pause = _d.pause; var set = useCallback(function (prop, value, isInstant) { // @ts-ignore target[prop] = value; // instant change if (isInstant) { // @ts-ignore moment[prop] = value; render(0); } else { // interpolated change play(); } onSet === null || onSet === void 0 ? void 0 : onSet(target); }, [moment, onSet, play, render, target]); var getMoment = useCallback(function () { return moment; }, [moment]); return { set: set, getMoment: getMoment }; } //# sourceMappingURL=useAnimationFrameSync.js.map