Edit Page

#MotionValue

MotionValues track the state and velocity of animating values.

All motion components internally use MotionValues 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 inject them into motion components.

import { motion, useMotionValue } from "framer-motion"

export function MyComponent() {
  const x = useMotionValue(0)
  return <motion.div style={{ x }} />
}

By manually creating MotionValues you can:

  • Set and get their state.
  • Pass to multiple components to synchronise motion across them.
  • Chain MotionValues via the useTransform hook.
  • Update visual properties without triggering React's render cycle.
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

MotionValues can be created with the useMotionValue hook.

const x = useMotionValue(0)

The value passed to useMotionValue will act as the initial state of the MotionValue.

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

MotionValues containing a single number can return a velocity via the getVelocity method. This returns the velocity as calculcated 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 MotionValues

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 MotionValues with the onChange method. onChange returns an unsubscribe method, so it works quite naturally with useEffect.

useEffect(() => x.onChange(latest => {}), [])

#Creating child MotionValues

Any MotionValue can spawn children MotionValues that update whenever their parent does. This allows the creation of value chains for declarative effects.

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 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.


#useMotionValue

#useMotionValue(initial): MotionValue<T>

Creates a MotionValue to track the state and velocity of a value.

Usually, these are created automatically. For advanced use-cases, like use with useTransform, you can create MotionValues externally and pass them into the animated component via the style prop.

export const MyComponent = () => {
  const scale = useMotionValue(1)

  return <motion.div style={{ scale }} />
}
initial: T

The initial state.

returns: MotionValue<T>

#useMotionTemplate

#useMotionTemplate(fragments, values): MotionValue<string>

Combine multiple motion values into a new one using a string template literal.

import {
  motion,
  useSpring,
  useMotionValue,
  useMotionTemplate
} from "framer-motion"

function Component() {
  const shadowX = useSpring(0)
  const shadowY = useMotionValue(0)
  const shadow = useMotionTemplate`drop-shadow(${shadowX}px ${shadowY}px 20px rgba(0,0,0,0.3))`

  return <motion.div style={{ filter: shadow }} />
}
fragments: TemplateStringsArray
values: MotionValue[]
returns: MotionValue<string>

#useTransform

#useTransform(input, transformer): MotionValue<O>

Create a MotionValue that transforms the output of another MotionValue through a function. In this example, y will always be double x.

export const MyComponent = () => {
  const x = useMotionValue(10)
  const y = useTransform(x, value => value * 2)

  return <motion.div style={{ x, y }} />
}
input: MotionValue<I>

A MotionValue that will pass its latest value through transform to update the returned MotionValue.

transformer: SingleTransformer<I, O>

A function that accepts the latest value from input and returns a new value.

returns: MotionValue<O>

MotionValue

#useTransform(input, transformer): MotionValue<O>

Pass an array of MotionValues and a function to combine them. In this example, z will be the x multiplied by y.

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 }} />
}
input: MotionValue<string | number>[]

An array of MotionValues that will pass their latest values through transform to update the returned MotionValue.

transformer: MultiTransformer<I, O>

A function that accepts the latest values from input and returns a new value.

returns: MotionValue<O>

MotionValue

#useTransform(value, inputRange, outputRange, options): MotionValue<O>

Create a MotionValue that transforms the output of another MotionValue by mapping it from one range of values into another.

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.

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 }}
    />
  )
}
value: MotionValue<number>

MotionValue

inputRange: InputRange

A linear series of numbers (either all increasing or decreasing)

outputRange: O[]

A series of numbers, colors or strings. Must be the same length as inputRange.

options: TransformOptions<O>
  • 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<O>

MotionValue


#useSpring

#useSpring(source, config): MotionValue<any>

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.

const x = useSpring(0, { stiffness: 300 })
const y = useSpring(x, { damping: 10 })
source: MotionValue | number

MotionValue or number. If provided a MotionValue, when the input MotionValue changes, the created MotionValue will spring towards that value.

config: SpringOptions

Configuration options for the spring.

returns: MotionValue<any>

MotionValue


#useElementScroll

#useElementScroll(ref): ScrollMotionValues

Returns MotionValues that update when the provided element scrolls:

  • scrollX — Horizontal scroll distance in pixels.
  • scrollY — Vertical scroll distance in pixels.
  • scrollXProgress — Horizontal scroll progress between 0 and 1.
  • scrollYProgress — Vertical scroll progress between 0 and 1.

This element must be set to overflow: scroll on either or both axes to report scroll offset.

export const MyComponent = () => {
  const ref = useRef()
  const { scrollYProgress } = useElementScroll(ref)

  return (
    <div ref={ref}>
      <motion.div style={{ scaleX: scrollYProgress }} />
    </div>
  )
}
ref: RefObject<HTMLElement>
returns: ScrollMotionValues

#useViewportScroll

#useViewportScroll(): ScrollMotionValues

Returns MotionValues that update when the viewport scrolls:

  • scrollX — Horizontal scroll distance in pixels.
  • scrollY — Vertical scroll distance in pixels.
  • scrollXProgress — Horizontal scroll progress between 0 and 1.
  • scrollYProgress — Vertical scroll progress between 0 and 1.
export const MyComponent = () => {
  const { scrollYProgress } = useViewportScroll()
  return <motion.div style={{ scaleX: scrollYProgress }} />
}
returns: ScrollMotionValues

#MotionValue API

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(v, render): void

Sets the state of the MotionValue.

const x = useMotionValue(0)
x.set(10)
v: V

Latest value to set.

render: boolean

Whether to notify render subscribers. Defaults to true

#isAnimating(): boolean

Returns true if this value is currently animating.

returns: boolean

#stop(): void

Stop the currently active animation.

#onChange(subscription): () => void

Adds a function that will be notified when the MotionValue is updated.

It returns a function that, when called, will cancel the subscription.

When calling onChange inside a React component, it should be wrapped with the useEffect hook. As it returns an unsubscribe function, this should be returned from the useEffect function to ensure you don't add duplicate subscribers..

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.onChange(updateOpacity)
    const unsubscribeY = y.onChange(updateOpacity)

    return () => {
      unsubscribeX()
      unsubscribeY()
    }
  }, [])

  return <motion.div style={{ x }} />
}
subscription: Subscriber<V>

A function that receives the latest value.

returns: () => void

A function that, when called, will cancel this subscription.

#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.