Motion values overview
Motion values track the state and velocity of animating values.
All motion
components internally use MotionValue
s to track the state and velocity of an animating value.
Usually, these are created automatically. But for advanced use-cases, it is possible to create them manually and provide them to motion
components.
import { motion, useMotionValue } from "framer-motion"
export function MyComponent() { const x = useMotionValue(0) return <motion.div style={{ x }} />}
By manually creating MotionValue
s you can:
- Set and get their state.
- Pass to multiple components to synchronise motion across them.
- Chain
MotionValue
s via theuseTransform
hook. - Update visual properties without triggering React's render cycle.
- Subscribe to updates.
const x = useMotionValue(0)const input = [-200, 0, 200]const output = [0, 1, 0]const opacity = useTransform(x, input, output)
return <motion.div drag="x" style={{ x, opacity }} />
#Overview
MotionValue
s can be created with the useMotionValue
hook.
The value passed to useMotionValue
will act as the initial state of the MotionValue
.
const x = useMotionValue(0)
It can be updated with the set
method. This won't trigger a React re-render.
x.set(100)
A MotionValue
can be any string or number. We can read the value with the get
method.
x.get() // 100
MotionValue
s containing a single number can return a velocity via the getVelocity
method. This returns the velocity as calculated per second to account for variations in frame rate across devices.
x.getVelocity()
If a MotionValue
contains a color, or more than one number, getVelocity
will always return 0
.
#Injecting MotionValue
s
Once a MotionValue
has been created, it can be injected into the motion
component in the same way you'd usually set that visual property.
For HTML components, that's via the style
attribute.
const x = useMotionValue(0)
return <motion.div style={{ x }} />
For SVG components, that's directly into the attribute itself.
const cx = useMotionValue(0)
return <motion.circle cx={cx} />
It is possible to inject a single MotionValue
into one or more components. Changes in the MotionValue
will be reflected in all the components.
#Responding to changes
Listeners can be added to MotionValue
s with the onChange
method. onChange
returns an unsubscribe method, so it works quite naturally with useEffect
.
useEffect(() => x.onChange(latest => {}), [])
#Composing MotionValues
Framer Motion provides multiple hooks for composing motion values, like useSpring and useTransform.
Using the useTransform
hook, we can pass the latest value through an update function that can take the latest parent value and transform it before returning it to update the child.
const y = useTransform(x, latest => latest * 2)
useTransform
can also accept value ranges that can map from a linear series of numbers into non-linear series of numbers, colors or a complex string.
const xInput = [-100, 0, 100]const opacityOutput = [0, 1, 0]const colorOutput = ["#f00", "#fff", "#0f0"]
const opacity = useTransform(x, xInput, opacityOutput)const color = useTransform(x, xInput, colorOutput)
These child components can be used exactly like the parents. They can be passed to the same component, a different component, or multiple other components.
#MotionValue
A MotionValue
has the following methods, with which you can query use to affect its state.
#get(): V
Returns the latest state of MotionValue
.
returns: V
The latest state of MotionValue
#getVelocity(): number
Returns the latest velocity of MotionValue
.
returns: number
The latest velocity of MotionValue
. Returns 0
if the state is nonnumerical
#set(newValue): void
Sets the MotionValue
to a new value.
const x = useMotionValue(0)x.set(10)
#jump(newValue): void
jump
sets the MotionValue
in a way that breaks continuity from previous values:
- Resets
velocity
to0
- Ends any active animation
- Ignores attached effects (for instance the spring attached to
MotionValue
s returned fromuseSpring
)
const x = useSpring(0)x.jump(10)x.getVelocity() // 0
#isAnimating(): boolean
Returns true
if this value is currently animating.
returns: boolean
#stop(): void
Stop the currently active animation.
#on(eventName, subscription): () => void
on
is used to subscribe to events on the MotionValue
.
x.on("change", latest => console.log(latest))
Available events are:
change
animationStart
animationCancel
animationComplete
It returns a function that, when called, will unsubscribe the listener.
const unsubscribe = x.on("change", latest => console.log(latest))
When calling on
inside a React component, it should be wrapped with a useEffect
hook.
subscription: Subscriber<V>
A function that receives the latest value
returns: () => void
A function that, when called, will cancel this subscription
export const MyComponent = () => { const x = useMotionValue(0) const y = useMotionValue(0) const opacity = useMotionValue(1)
useEffect(() => { function updateOpacity() { const maxXY = Math.max(x.get(), y.get()) const newOpacity = transform(maxXY, [0, 100], [1, 0]) opacity.set(newOpacity) }
const unsubscribeX = x.on("change", updateOpacity) const unsubscribeY = y.on("change", updateOpacity)
return () => { unsubscribeX() unsubscribeY() } }, [])
return <motion.div style={{ x }} />}
Alternatively, the useMotionValueEvent hook can be used to do this automatically.
useMotionValueEvent(x, "change", latest => console.log(latest))
#destroy(): void
Destroy and clean up subscribers to this MotionValue
.
The MotionValue
hooks like useMotionValue
and useTransform
automatically handle the lifecycle of the returned MotionValue
, so this method is only necessary if you've manually created a MotionValue
via the motionValue
function.