With the Framer Motion library, we can render animations in our React app easily.
In this article, we’ll take a look at how to get started with Framer Motion.
useElementScroll
The useElementScroll
hook returns motion values that updated when the element scrolls.
For example, we can write:
import React, { useRef } from "react";
import { motion, useElementScroll } from "framer-motion";
export default function App() {
const ref = useRef();
const { scrollYProgress } = useElementScroll(ref);
return (
<div ref={ref} style={{ overflow: "scroll", height: 200 }}>
<motion.div style={{ scaleY: scrollYProgress }}>
{Array(100)
.fill()
.map((_, i) => (
<p key={i}>{i}</p>
))}
</motion.div>
</div>
);
}
We set the scaleY
value to the scrollYProgress
motion value.
Then the p
elements that are lower are taller.
We just have the overflow
property set to 'scroll'
and a fixed height for this hook to calculate the scroll progress.
useViewportScroll
The useViewportScroll
hook returns the motion values that update when the viewport scrolls.
For example, we can write:
import React, { useEffect } from "react";
import { motion, useViewportScroll } from "framer-motion";
export default function App() {
const { scrollYProgress } = useViewportScroll();
useEffect(() => {
scrollYProgress.onChange((latest) => {
console.log(latest);
});
}, []);
return (
<motion.div>
{Array(100)
.fill()
.map((_, i) => (
<p key={i}>{i}</p>
))}
</motion.div>
);
}
to get the scrollYProgress
, which has the latest value of the vertical scroll progress.
Its value is between 0 and 1.
The value is set as the value of the latest
parameter.
Other value this hook returns includes scrollX
, which is the horizontal scroll distance in pixels.
The scrollY
motion value has the vertical scroll distance in pixels.
And scrollXProgress
has the horizontal scroll progress between 0 and 1.
onChange
We can watch for motion value changes with the onChange
method.
For example, we can call it by writing:
import { motion, transform, useMotionValue } from "framer-motion";
import React, { useEffect } from "react";
export default function App() {
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.1]);
opacity.set(newOpacity);
}
const unsubscribeX = x.onChange(updateOpacity);
const unsubscribeY = y.onChange(updateOpacity);
return () => {
unsubscribeX();
unsubscribeY();
};
}, []);
return (
<motion.div
drag
style={{ x, opacity, backgroundColor: "red", width: 100, height: 100 }}
/>
);
}
We call onChange
in the useEffect
callback.
We call x.onChange
to watch the latest value of x
.
And we call y.onChange
to watch the latest value of y
.
It returns a function to let us unsubscribe to the changes.
The updateOpacity
function gets the latest value of x
and y
and then compute the opacity from it.
We call opacity.set
to set the value of the opacity
motion value.
Then we render the values by passing it into the style
prop.
destroy
The destroy
method destroys and clean up subscribers.
We call this on a motion value object.
Conclusion
We can watch for motion value changes to create animations with Framer Motion.
Also, we can watch for scrolling progress with it.