Replies: 3 comments
-
@mattgperry could you take a look at this |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Beta Was this translation helpful? Give feedback.
0 replies
-
@mattgperry import { useRef, useContext, useInsertionEffect } from "react"
import { MotionValue } from "../value"
import { isMotionValue } from "./utils/is-motion-value"
import { useMotionValue } from "./use-motion-value"
import { MotionConfigContext } from "../context/MotionConfigContext"
import { SpringOptions } from "../animation/types"
import { useIsomorphicLayoutEffect } from "../utils/use-isomorphic-effect"
import { frame, frameData } from "../frameloop"
import {
MainThreadAnimation,
animateValue,
} from "../animation/animators/MainThreadAnimation"
function toNumber(v: string | number) {
if (typeof v === "number") return v === -Infinity ? "auto" : v
// 👆
return parseFloat(v)
}
/**
* Creates a `MotionValue` that, when `set`, will use a spring animation to animate to its new state.
*
* It can either work as a stand-alone `MotionValue` by initialising it with a value, or as a subscriber
* to another `MotionValue`.
*
* @remarks
*
* ```jsx
* const x = useSpring(0, { stiffness: 300 })
* const y = useSpring(x, { damping: 10 })
* ```
*
* @param inputValue - `MotionValue` or number. If provided a `MotionValue`, when the input `MotionValue` changes, the created `MotionValue` will spring towards that value.
* @param springConfig - Configuration options for the spring.
* @returns `MotionValue`
*
* @public
*/
export function useSpring(
source: MotionValue<string> | MotionValue<number> | number,
config: SpringOptions = {}
) {
const { isStatic } = useContext(MotionConfigContext)
const activeSpringAnimation = useRef<MainThreadAnimation<number> | null>(
null
)
const value = useMotionValue(
isMotionValue(source) ? toNumber(source.get()) : source
)
const latestValue = useRef<number>(value.get())
const latestSetter = useRef<(v: number) => void>(() => {})
const startAnimation = () => {
/**
* If the previous animation hasn't had the chance to even render a frame, render it now.
*/
const animation = activeSpringAnimation.current
if (animation && animation.time === 0) {
animation.sample(frameData.delta)
}
stopAnimation()
activeSpringAnimation.current = animateValue({
keyframes: [value.get(), latestValue.current].filter(v => Number(v)),
// 👆
velocity: value.getVelocity(),
type: "spring",
restDelta: 0.001,
restSpeed: 0.01,
...config,
onUpdate: latestSetter.current,
})
}
const stopAnimation = () => {
if (activeSpringAnimation.current) {
activeSpringAnimation.current.stop()
}
}
useInsertionEffect(() => {
return value.attach((v, set) => {
/**
* A more hollistic approach to this might be to use isStatic to fix VisualElement animations
* at that level, but this will work for now
*/
if (isStatic) return set(v)
latestValue.current = v
latestSetter.current = set
frame.update(startAnimation)
return value.get()
}, stopAnimation)
}, [JSON.stringify(config)])
useIsomorphicLayoutEffect(() => {
if (isMotionValue(source)) {
return source.on("change", (v) => value.set(toNumber(v)))
}
}, [value])
return value
} I added two changes, and it seems to work I'm not sure what should be considered an invalid value for this change allows us to use let [ref, {height}] = useMeasure();
const springyHeight = useSpring(height, springOptions); instead of what I shared in first message |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi everyone,
I have a motion value that tracks height, the thing is it starts as
null
when I feed this motion value to useSpring, it does not work
something like this
I found a workaround like this
Is this a bug, is useSpring intended to work this way?
Beta Was this translation helpful? Give feedback.
All reactions