u/Upper-Click-9445

Image 1 — GSAP + React: How can I move an image into a target container on scroll?
Image 2 — GSAP + React: How can I move an image into a target container on scroll?
Image 3 — GSAP + React: How can I move an image into a target container on scroll?
Image 4 — GSAP + React: How can I move an image into a target container on scroll?
▲ 4 r/react+1 crossposts

GSAP + React: How can I move an image into a target container on scroll?

import { RefObject } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useGSAP } from "@gsap/react";


gsap.registerPlugin(ScrollTrigger);


type HeroAnimationRefs = {
  heroSectionRef: RefObject<HTMLElement | null>;
  heroTextRef: RefObject<HTMLDivElement | null>;
  floatingImageRef: RefObject<HTMLDivElement | null>;
  storyTargetRef: RefObject<HTMLDivElement | null>;
};


export default function useHeroAnimation({
  heroSectionRef,
  heroTextRef,
  floatingImageRef,
  storyTargetRef,
}: HeroAnimationRefs) {
  useGSAP(() => {
    if (
      !heroSectionRef.current ||
      !heroTextRef.current ||
      !floatingImageRef.current ||
      !storyTargetRef.current
    ) {
      return;
    }


    const imageRect = floatingImageRef.current.getBoundingClientRect();
    const targetRect = storyTargetRef.current.getBoundingClientRect();


    const imageCenterX = imageRect.left + imageRect.width / 2;
    const imageCenterY = imageRect.top + imageRect.height / 2;


    const targetCenterX = targetRect.left + targetRect.width / 2;
    const targetCenterY = targetRect.top + targetRect.height / 2;


    const x = targetCenterX - imageCenterX;
    const y = targetCenterY - imageCenterY;


    const scale = Math.min(
      targetRect.width / imageRect.width,
      targetRect.height / imageRect.height,
    );


    const tl = gsap.timeline({
      scrollTrigger: {
        trigger: heroSectionRef.current,
        start: "top top",
        end: "bottom top",
        // pin: true,
        scrub: 1,
        markers: true,
        invalidateOnRefresh: true,
      },
    });


    tl.to(
      heroTextRef.current,
      {
        opacity: 0,
        y: -250,
        ease: "none",
      },
      0,
    );


    tl.to(
      floatingImageRef.current,
      {
        x,
        y,
        // scale,
        transformOrigin: "center center",
        ease: "none",
      },
      0,
    );


    ScrollTrigger.refresh();
  });
}

I'm trying to animate the hero image so that it moves into the red box while scrolling. I calculated the distance using getBoundingClientRect(), but the result isn't what I expected. Could someone point out what I'm doing wrong? Here's my code:

u/Upper-Click-9445 — 3 days ago