UNPKG

@anton.bobrov/react-vevet-hooks

Version:

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

84 lines (83 loc) 3.3 kB
"use strict"; 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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useAnimationFrameSync = void 0; var react_hooks_1 = require("@anton.bobrov/react-hooks"); var react_1 = require("react"); var vevet_1 = require("vevet"); var useAnimationFrame_1 = require("./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 */ 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 = (0, react_hooks_1.useEvent)(onUpdateProp); var onSet = (0, react_hooks_1.useEvent)(onSetProp); var dataRef = (0, react_1.useRef)({ moment: __assign({}, initialData), target: __assign({}, initialData), }); var props = (0, react_hooks_1.objectKeys)(initialData); var _c = dataRef.current, moment = _c.moment, target = _c.target; var render = (0, react_hooks_1.useEvent)(function (ease) { props.forEach(function (prop) { // @ts-ignore moment[prop] = (0, vevet_1.lerp)(moment[prop], target[prop], ease); }); onUpdate(moment); }); var _d = (0, useAnimationFrame_1.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 = (0, react_1.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 = (0, react_1.useCallback)(function () { return moment; }, [moment]); return { set: set, getMoment: getMoment }; } exports.useAnimationFrameSync = useAnimationFrameSync;