Jump to content
Search Community

How to use scrollTrigger to scrub through a video so that the video stays at the end when scrolled past (React)

Hiemas

Recommended Posts

Posted

I've managed to get video scrubbing working in a react project using the scroll trigger
however once I pass the end the video snaps to first frame, and jumps back to the end if i scroll back up into the timeline is there a way to retain the value after the end position

here is a video of what is currently happening
https://streamable.com/sm47e4

here is a stripped down part of the code to only include relevant parts
 

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

gsap.registerPlugin(ScrollTrigger, useGSAP);

const ScrollTimeline: React.FC<ScrollTimelineProps> = ({ }) => {
  const testRef = useRef(null);
  const elRef = useRef(null);
  const videoRef = useRef<VideoRef>(null);

  useGSAP(() => {
    const trigger = testRef.current;

    const tl = gsap.timeline({
      defaults: { duration: 1 },
      scrollTrigger: {
        trigger: trigger,
        start: "top top",
        pin: true,
        end: "+=600%",
        scrub: true
      }
    });

    const el = elRef.current;
    tl
    .fromTo(
      el,
      {
        rotation: 0
      },
      {
        rotation: 180
      }
      , 0
    )

    // FIX THIS, GET REF PROPERLY
    // This is to just get the video element after its properly rendered
    var interval
    if (!initialised) {
      setInitialised(true)
      interval = setInterval(() => {
        const videoEl = document.querySelector('video')
        if (videoEl) {
        	clearInterval(interval);

			tl.fromTo(
				videoEl,
				{
					currentTime: 0
				},
				{
					currentTime: videoEl.duration,
				},
				0
			)
        }
      }, 2000)
    }
  }, []);

  return (
    <div className={clsx(styles.page)}>
      <div className={clsx(styles.scrollTimeline)} ref={testRef}>

      	{/* This element contains the video element */}
        <BackgroundMedia {...mediaArgs} />
        <div className={clsx(styles.test)} ref={elRef}>
          TEST
        </div>
      </div>
    </div>
  );
}

 

Posted

Hi @Hiemas and welcome to the GSAP Forums!

 

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen.

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import GSAP as shown in the Install Helper in our Learning Center : 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

This looks kind of weird to me:

var interval
if (!initialised) {
  setInitialised(true)
  interval = setInterval(() => {
    const videoEl = document.querySelector('video')
    if (videoEl) {
      clearInterval(interval);
      tl.fromTo(
        videoEl,
        {
          currentTime: 0
        },
        {
          currentTime: videoEl.duration,
        },
        0
      )
    }
  }, 2000)
}

What exactly is the purpose of this block of code? If you want to wait for the video to be loaded just use the loadedmetadata event:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loadedmetadata_event

 

Like this:

videoEl.onloadedmetadata = function () {
  tl.to(videoEl, { currentTime: videoEl.duration });
};

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...