motiondivision / motion

A modern animation library for React and JavaScript
https://motion.dev
MIT License
25.84k stars 849 forks source link

Pausing useTransform / changing bounds during scroll #2775

Open aidan-rypens opened 3 months ago

aidan-rypens commented 3 months ago

Hello! Is there a way to 'pause' the useTransform hook any way?

What I'd like to achieve:

I've tried the following:

Use IntersectionObserver to check when the last box is in view and then alter the range of the transform. So for example, if it was x: -65%, set value as following: useTransform(scrollYProgress, [0, 1], ["-65%", "0%"]).

Implementation, inside hook:

if (entry.isIntersecting && xOffset === initialXOffset) {
   setXOffset(transformation.get());
}

This works, but there is a 'jump' because the initial value (for example -80%) makes it jump.

Is there a way to calculate this or to 'pause' the useTransform or am I using the wrong tool for the job here? Is there a way to calculate this beforehand? Or to 'run' this animation in the background on loading?

image

And when you scroll down, move from right to left:

image

"use client";

import { motion, useScroll, useTransform } from "framer-motion";
import { useRef } from "react";

export default function BoxesScrollStrip() {
  const targetRef = useRef(null);
  const { scrollYProgress } = useScroll({
    target: targetRef,
  });

  // Move the strip from right to left as you scroll down
  const x = useTransform(scrollYProgress, [0, 1], ["-20%", "0%"]);

  return (
    <div ref={targetRef} className="w-full overflow-x-hidden">
      <motion.div style={{ x }} className="flex gap-4 pl-[10%]">
        {Array.from({ length: 3 }).map((_, index) => (
          <div
            key={index}
            className="aspect-[3/2] bg-red-500 w-[35%] flex-shrink-0 flex justify-center items-center text-5xl"
          >
            {index}
          </div>
        ))}
      </motion.div>
    </div>
  );
}