Categories
React

Framer Motion — Scrolling and Watching Motion Values

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *