Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | 31x 31x 31x 31x 46x 46x 78x 78x 46x 46x 94x 94x 94x 110x 94x | import { MotionValue } from "../value" import { transform, TransformOptions } from "../utils/transform" import { useCombineMotionValues } from "./use-combine-values" import { useConstant } from "../utils/use-constant" export type InputRange = number[] type SingleTransformer<I, O> = (input: I) => O type MultiTransformer<I, O> = (input: I[]) => O type Transformer<I, O> = | SingleTransformer<I, O> /** * Ideally, this would be typed <I, O> in all instances, but to type this * more accurately requires the tuple support in TypeScript 4: * https://gist.github.com/InventingWithMonster/c4d23752a0fae7888596c4ff6d92733a */ | MultiTransformer<string | number, O> /** * Create a `MotionValue` that transforms the output of another `MotionValue` by mapping it from one range of values into another. * * @remarks * * Given an input range of `[-200, -100, 100, 200]` and an output range of * `[0, 1, 1, 0]`, the returned `MotionValue` will: * * - When provided a value between `-200` and `-100`, will return a value between `0` and `1`. * - When provided a value between `-100` and `100`, will return `1`. * - When provided a value between `100` and `200`, will return a value between `1` and `0` * * * The input range must be a linear series of numbers. The output range * can be any value type supported by Framer Motion: numbers, colors, shadows, etc. * * Every value in the output range must be of the same type and in the same format. * * ```jsx * export const MyComponent = () => { * const x = useMotionValue(0) * const xRange = [-200, -100, 100, 200] * const opacityRange = [0, 1, 1, 0] * const opacity = useTransform(x, xRange, opacityRange) * * return ( * <motion.div * animate={{ x: 200 }} * style={{ opacity, x }} * /> * ) * } * ``` * * @param inputValue - `MotionValue` * @param inputRange - A linear series of numbers (either all increasing or decreasing) * @param outputRange - A series of numbers, colors or strings. Must be the same length as `inputRange`. * @param options - * * - clamp: boolean. Clamp values to within the given range. Defaults to `true` * - ease: EasingFunction[]. Easing functions to use on the interpolations between each value in the input and output ranges. If provided as an array, the array must be one item shorter than the input and output ranges, as the easings apply to the transition between each. * * @returns `MotionValue` * * @public */ export function useTransform<I, O>( value: MotionValue<number>, inputRange: InputRange, outputRange: O[], options?: TransformOptions<O> ): MotionValue<O> /** * Create a `MotionValue` that transforms the output of another `MotionValue` through a function. * In this example, `y` will always be double `x`. * * ```jsx * export const MyComponent = () => { * const x = useMotionValue(10) * const y = useTransform(x, value => value * 2) * * return <motion.div style={{ x, y }} /> * } * ``` * * @param input - A `MotionValue` that will pass its latest value through `transform` to update the returned `MotionValue`. * @param transform - A function that accepts the latest value from `input` and returns a new value. * @returns `MotionValue` * * @public */ export function useTransform<I, O>( input: MotionValue<I>, transformer: SingleTransformer<I, O> ): MotionValue<O> /** * Pass an array of `MotionValue`s and a function to combine them. In this example, `z` will be the `x` multiplied by `y`. * * ```jsx * export const MyComponent = () => { * const x = useMotionValue(0) * const y = useMotionValue(0) * const z = useTransform([x, y], [latestX, latestY] => latestX * latestY) * * return <motion.div style={{ x, y, z }} /> * } * ``` * * @param input - An array of `MotionValue`s that will pass their latest values through `transform` to update the returned `MotionValue`. * @param transform - A function that accepts the latest values from `input` and returns a new value. * @returns `MotionValue` * * @public */ export function useTransform<I, O>( input: | MotionValue<string>[] | MotionValue<number>[] | MotionValue<string | number>[], transformer: MultiTransformer<I, O> ): MotionValue<O> export function useTransform<I, O>( input: | MotionValue<I> | MotionValue<string>[] | MotionValue<number>[] | MotionValue<string | number>[], inputRangeOrTransformer: InputRange | Transformer<I, O>, outputRange?: O[], options?: TransformOptions<O> ): MotionValue<O> { const transformer = typeof inputRangeOrTransformer === "function" ? inputRangeOrTransformer : transform(inputRangeOrTransformer, outputRange!, options) return Array.isArray(input) ? useListTransform( input, transformer as MultiTransformer<string | number, O> ) : useListTransform([input], ([latest]) => (transformer as SingleTransformer<I, O>)(latest) ) } function useListTransform<I, O>( values: MotionValue<I>[], transformer: MultiTransformer<I, O> ): MotionValue<O> { const latest = useConstant<I[]>(() => []) return useCombineMotionValues(values, () => { latest.length = 0 const numValues = values.length for (let i = 0; i < numValues; i++) { latest[i] = values[i].get() } return transformer(latest) }) } |