Last active
May 13, 2022 06:35
-
-
Save steveruizok/c91232271826e58ea4752f344911f8fe to your computer and use it in GitHub Desktop.
Declare a motion value with a value computed from multiple other values.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from "react" | |
import { MotionValue, useMotionValue } from "framer" | |
/** | |
* UseRelative | |
* @description Declare a motion value with a value dependent on multiple other values. | |
* @param parents An array of motion values or values. | |
* @param transform A function that receives the current values and returns a computed value. | |
* @example | |
* ```jsx | |
* const knobHeight = useRelative( | |
* [scrollHeight, contentHeight, maskHeight], | |
* (scrollHeight, contentHeight, maskHeight) => { | |
* return maskHeight * (scrollHeight / contentHeight) | |
* } | |
*) | |
*``` | |
*/ | |
export function useRelative<T>( | |
parents: (MotionValue<T> | T)[], | |
transform: (...parents: T[]) => T | |
) { | |
const transformedValue = useMotionValue(transform(...parents.map(toValue))) | |
useEffect(() => { | |
const computeValue = () => | |
transformedValue.set(transform(...parents.map(toValue))) | |
computeValue() | |
const removers = parents | |
.map(v => isMotionValue(v) && v.onChange(computeValue)) | |
.filter(v => v) as (() => void)[] | |
return () => removers.forEach(fn => fn()) | |
}, [...parents, transform]) | |
return transformedValue | |
} | |
// HELPERS | |
export const isMotionValue = (value: any): value is MotionValue => { | |
return value instanceof MotionValue | |
} | |
const toValue: <T>(v: MotionValue<T> | T) => T = v => | |
isMotionValue(v) ? v.get() : v |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment