Jump to content
Search Community

Scrubbing through several successive pinned videos with ScrollTrigger

flux_capacitor test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Hi, 
I can't find any tutorial to scrub through several pinned MP4 videos natively with ScrollTrigger. Everything out there is about bitmap or vector animations (which I understand, as GSAP is primarily focused on such kind of animation). Maybe those tutorials do exist, but i didn't find them. What I found is people sometimes asking for this, in order to build for example Apple-like transitions. Alas pretty much all answers redirect them to existing topics about sprite or canvas animations (what Apple does indeed). But a sprite animation is not scrubbing through a video, so the initial question remains unanswered.

 

Topics or CodePen addressing video scrubbing control do exist, like this one:

 

See the Pen 9e810322d70c306de2d18237d0cb2d78 by shshaw (@shshaw) on CodePen

 

found in this topic, see also this other topic, or the deprecated solution below) but most of them are a mix of traditional scrubbing with HTML5+Javascript using fullscreen videos in CSS "fixed" position, using an invisible "wrapper", "container" or "spacer" whatever one calls them, i.e. a very long element of several hundreds pixels or vh height making use of  ScrollTop to control the scrubbing length amount, instead of the smart start/end point markers provided natively by GSAP and ScrollTrigger.

 

What about controlling (i.e. pinning & scrubbing through) several successive short videos (that are not fullscreen) with mouse/trackpad on a single web page? Is it possible to do that natively (without a long spacer scrolling) with ScrollTrigger ? I discover GSAP and I am still a beginner.

 

PS: my question does not deal with choppy scrubbing of MP4 videos in some browsers or devices as I already understood codec constraints with the correct amount of GOP, I- and B-frames and the overall video encoding optimization process to achieve smooth animations.

See the Pen Jjozjgw by melo07 (@melo07) on CodePen

Link to comment
Share on other sites

Welcome to the forums @flux_capacitor

 

I'm a little unsure about what you're asking here. People use spacing to control the speed of scrubbing. You can set that however you want. And videos don't have to be fullscreen, and can be pinned just like any other element. All the sprite animations threads you're referring to would work pretty much the same for video. The only difference is the property you are animating. 

 

If you don't want to use native scrolling, then you would have to use wheel events.

 

Link to comment
Share on other sites

It also sounds like you are trying to approach this like video has be treated in a special way. Video does have some special considerations, like making sure it's loaded, but that's about it. 

 

If you're just getting started, I would experiment without video. Set up your page how you want using boxes as placeholders for the video, and then scrub changing the background color. Once you have the layout and scrub speed like you want, then just replace those boxes with your videos.

  • Like 3
Link to comment
Share on other sites

Then yes I am mistaken, because I can perfectly make a simple animation of a single or several 2D elements with ScrollTrigger, e.g. say, creating several boxes in an HTML page with CSS then animate their path along the X or Y axis on screen, or modifying some of their CSS properties like background color and alpha values. This is indeed very simple according to the various tutorials out there.

 

However I don't see what animated paths and CSS properties have in common with parsing a video. This is way more difficult with respect to the syntax and the code length compared to just moving boxes or filling them with a color. Especially when adding several videos on page.

 

To show this I forked shshaw's example here: 

See the Pen dyRXPwd by flux_capacitor (@flux_capacitor) on CodePen

 

As you can see the code is not as simple as moving green and blue boxes on screen, especially if you want the video to be scrubbed on a smartphone also. So far I managed to achieve two things:

  1. Get rid of the fixed position of the fullscreen video, replacing it with the pinning property natively provided by ScrollTrigger. The video now scrolls with the text until it reaches a specific position near the top of the window, then it stops there (is pinned) and scrubs through its content while the user continues scrolling, and finally when the video reaches the end it resumes scrolling with text.
  2. Get rid of the invisible long scrolling container whose position controlled scrubbing in shshaw's previous example, replacing it with ScrollTrigger's native scrub and end properties.

But I fail to see how I could control the same way subsequent similar other videos down in the page flow.

Link to comment
Share on other sites

59 minutes ago, flux_capacitor said:

However I don't see what animated paths and CSS properties have in common with parsing a video.

 

Everything. GSAP isn't parsing a video, it's just changing the currentTime property. It's no different than changing the background color of a box. And a video element is part of the document flow, so ScrollTrigger will treat pinning and triggering just like any other element.

 

gsap.to(box, {
  backgroundColor: "blue",
  scrollTrigger: {
    scrub: true,
    ...
  }
});

gsap.to(video1, {
  currentTime: video1.duration,
  scrollTrigger: {
    scrub: true,
    ...
  }
});

gsap.to(video2, {
  currentTime: video2.duration,
  scrollTrigger: {
    scrub: true,
    ...
  }
});

 

Of course with video you need to make sure it's loaded first, which is what that demo was doing, but that's really not a GSAP issue. That's just a requirement of working with video itself.

 

  • Like 3
Link to comment
Share on other sites

  • Solution

Here's a fork that shows how easy it could be with a helper function: 

See the Pen xxrOdpj?editors=0010 by GreenSock (@GreenSock) on CodePen

 

I didn't understand the point of that blob stuff and it actually seemed to cause problems because it was setting the src of the video to a totally different URL that caused the duration to be NaN, so I removed that.

 

HELPER FUNCTION

function videoScrub(video, vars) {
  video = gsap.utils.toArray(video)[0]; // in case selector text is fed in.
  let once = (el, event, fn) => {
        let onceFn = function () {
          el.removeEventListener(event, onceFn);
          fn.apply(this, arguments);
        };
        el.addEventListener(event, onceFn);
        return onceFn;
      },
      prepFunc = () => { video.play(); video.pause(); },
      prep = () => once(document.documentElement, "touchstart", prepFunc),
      src = video.currentSrc || video.src,
      tween = gsap.fromTo(video, {currentTime: 0}, {paused: true, immediateRender: false, currentTime: video.duration || 1, ease: "none", ...vars}),
      resetTime = () => (tween.vars.currentTime = video.duration || 1) && tween.invalidate();
  prep();
  video.readyState ? resetTime() : once(video, "loadedmetadata", resetTime);
  return tween;
}

USAGE 

videoScrub(videoElement, {
  scrollTrigger: {
    trigger: videoElement,
    start: "center center",
    scrub: true,
    pin: true
  },
  onUpdate: () => console.log(videoElement.currentTime)
});

 

So you can just loop through all the videos with a certain class in one fell swoop and apply the same effect: 

gsap.utils.toArray(".video-scrub").forEach(video => videoScrub(video, {
  scrollTrigger: {
    trigger: video,
    start: "center center",
    end: "+=600",
    scrub: true,
    pin: true
  }
}));

 

Does that clear things up? 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Thank you OSUblake! I was completely off the mark. I eventually understood with your help :)

I've updated my CodePen with a for loop to shorten then code length using simple incremental ids for each subsequent <video> element in the page.

This simple code does the trick, provided the start & end points are the same so the video lengths (rate of scroll) are pretty much the same.

As I kept shshaw's original functions, the code works on touchscreens and check that the videos are loaded.

 

See the Pen dyRXPwd by flux_capacitor (@flux_capacitor) on CodePen

  • Like 2
Link to comment
Share on other sites

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...