useTransform
Create a new motion value that transforms the output of one or more other motion values.
useTransform
is the primary way to compose chains of motion values. That is, to take the output of one motion value, change it some way, and then output that as a new motion value.
#Usage
Import from Framer Motion.
import { useTransform } from "framer-motion"
#Mapping
useTransform
can map a motion value from one range of values to another.
To illustrate, look at this x
motion value:
const x = useMotionValue(0)
We can use useTransform
to create a new motion value called opacity
. By defining an input range and an output range we can say, "when x
is 0
, opacity
should be 1
. When x
is 100
, opacity
should be 0."
const opacity = useTransform( x, // Map x from these values: [0, 100], // Into these values: [1, 0])
Now, if x
gets set to 50
, opacity
will be 0.5
.
Both ranges must always be the same length.
The input range must always be a linear series of numbers, either counting up or counting down.
The output range must all be of the same type, but can be any type supported by Framer Motion, for instance numbers, colors, shadows etc.
const backgroundColor = useTransform( x, [0, 100], ["#f00", "#00f"])
It's possible to provide more than two values to each range. For instance, with the following mapping, we fade opacity
out whenever x
goes outside of the 0-100
range.
const opacity = useTransform( x, [-100, 0, 100, 200], [0, 1, 1, 0])
By setting clamp: false
, the ranges will map perpetually. For instance, in this example we're saying "for every 100px scrolled, rotate another 360deg":
const { scrollY } = useViewportScroll()const rotate = useTransform( scrollY, [0, 100], [0, 360], { clamp: false })
#Functions
More complex transforms can be created by passing a function.
For instance, we can create a wavy motion by using Math.sin
on an x
motion value:
export const MyComponent = () => { const x = useMotionValue(10) const y = useTransform(x, value => Math.cos(value / 10) * 50)
return <motion.div style={{ x, y }} />}
#Combine multiple values
Pass an array of motion values and the provided function will receive the latest ouput as an array.
export const MyComponent = () => { const x = useMotionValue(0) const y = useSpring(0) const z = useTransform( [x, y], ([latestX, latestY]) => latestX * latestY )
return <motion.div style={{ x, y, z }} />}
#Options
When passing ranges, we can also pass an object of options as the final argument.
useTransform(value, input, output, options)
#clamp: boolean
Default: true
If true
, will clamp output to within the provided range. If false
, will carry on mapping even when the input falls outside the provided range.
const y = useTransform(x, [0, 1], [0, 2])const z = useTransform(x, [0, 1], [0, 2], { clamp: false })
useEffect(() => { x.set(2) console.log(y.get()) // 2, input clamped console.log(z.get()) // 4})
#ease: EasingFunction | EasingFunction[]
An easing function, or list of easing functions, to use to ease the mixing between each value in the provided ranges.
These must be JavaScript functions. All named easings can be imported from "framer-motion"
:
import { cubicBezier, circOut } from "framer-motion"
// In your componentconst y = useTransform(x, [0, 1], [0, 2], { ease: circOut })
const z = useTransform( x, [0, 1], [0, 2], { ease: cubicBezier(0.17, 0.67, 0.83, 0.67) })
#mixer: (from: T, to: T) => (p: number) => any
A function to use to mix between each set of output value.
This can be used to inject more advanced mixers than Framer Motion's default, for instance Flubber for morphing SVG paths.
from
and to
will be each set of values, for instance given an output range ["#000", "#f00", "#333"]
two mixers will be created, one between "#000"
and "#f00"
and one between "#f00"
and "#333"
.
p
is an eased progress value between 0
and 1
that defines how much we should mix between from
and to
.