UNPKG

@shopify/react-native-skia

Version:

High-performance React Native Graphics using Skia

90 lines (81 loc) 1.98 kB
import type { ExtrapolationType, SharedValue } from "react-native-reanimated"; import { useMemo } from "react"; import type { SkPath, SkPoint } from "../../skia/types"; import { interpolatePaths, interpolateVector } from "../../animation"; import { Skia } from "../../skia"; import { useAnimatedReaction, useFrameCallback, useSharedValue, } from "./moduleWrapper"; export const notifyChange = (value: SharedValue<unknown>) => { "worklet"; // eslint-disable-next-line @typescript-eslint/no-explicit-any (value as any)._value = value.value; }; export const useClock = () => { const clock = useSharedValue(0); useFrameCallback((info) => { clock.value = info.timeSinceFirstFrame; }); return clock; }; /** * @worklet */ type Interpolator<T> = ( value: number, input: number[], output: T[], options: ExtrapolationType, result: T ) => T; const useInterpolator = <T>( factory: () => T, value: SharedValue<number>, interpolator: Interpolator<T>, input: number[], output: T[], options?: ExtrapolationType ) => { // eslint-disable-next-line react-hooks/exhaustive-deps const init = useMemo(() => factory(), []); const result = useSharedValue(init); useAnimatedReaction( () => value.value, (val) => { result.value = interpolator(val, input, output, options, result.value); notifyChange(result); }, [input, output, options] ); return result; }; export const usePathInterpolation = ( value: SharedValue<number>, input: number[], outputRange: SkPath[], options?: ExtrapolationType ) => useInterpolator( () => Skia.Path.Make(), value, interpolatePaths, input, outputRange, options ); export const useVectorInterpolation = ( value: SharedValue<number>, input: number[], outputRange: SkPoint[], options?: ExtrapolationType ) => useInterpolator( () => Skia.Point(0, 0), value, interpolateVector, input, outputRange, options );