Jump to content
GreenSock

merlin

ScrollTrigger + ScrollSmoother shaky touch scroll using scrub and pin

Recommended Posts

Hi there!

 

I tried combining ScrollSmoother with scrub/pin timelines.

Apparently when using a touch-device (or devtools device emulator) it gets extremely shaky when "touch" to scroll.

 

I was wondering if there's anything wrong with the code or that it's a bug?

 

This CSB is a really small example of what i'm doing in a project, where the problem is arising as well.

 

Steps to reproduce:

- Open devtools -> mobile view -> iphone 12

- Use mouse to drag on screen (long drag, flicks work!)

 

 

https://codesandbox.io/s/scrollsmoother-gsap-test-forked-ipydx4

Edited by merlin
Did an oopsie with Codepen url
  • Like 1
Link to comment
Share on other sites

Some background:


We're building a website where we are scrolling through 3D canvas scenes.

So we use the onUpdate function to get the scrollTop value.

The scrollTop value is then used in Canvas to animate things to tell a story.

Since we use multiple components, we also have multiple scrollTriggers.

 

That's why we need ScrollSmoother, scrub and pin :)

 

Link to comment
Share on other sites

Thanks Cassie!

It seems like this fixes the shaky scroll:

 

  useLayoutEffect(() => {
    ScrollTrigger.normalizeScroll(true);

    const smoothScroll = ScrollSmoother.create({
      smooth: 1, // how long (in seconds) it takes to "catch up" to the native scroll position
      // This causes buttons to scroll to top =======================================================================
      // smoothTouch: 0, // much shorter smoothing time on touch devices (default is NO smoothing on touch devices)
      ignoreMobileResize: true,
      // normalizeScroll: true,
      onUpdate: x => {
        useScrollValue.setState({ scrollValue: x.scrollTop() });
      },
    });

    if (window.location.hash) {
      smoothScroll.scrollTo(window.location.hash, true);
    }

    return () => {
      smoothScroll.kill();
    };
  }, []);

 

  • Like 3
Link to comment
Share on other sites

@Cassie
Previously we thought normalizeScroll fixed the "shaky" scroll. Sadly, it only works when resizing from desktop to mobile size.

When I refresh on mobile size, or open the website on mobile, the shakiness remains.

Are there any other things I can try next to normalizeScroll?

Link to comment
Share on other sites

Hi there, have you updated the demo with the latest code?

Link to comment
Share on other sites

I'm trying to recreate one as accurate as possible!

  • Like 1
Link to comment
Share on other sites

I'm a little confused now. The issue is on chrome on desktop now? Not on mobile? Can you break this down again for me - just let me know exactly what the issue is and how to recreate? (sorry)

Also if mobile is the issue and you're not using ScrollSmoother for normalize scroll, or effects or smoothing, maybe only create it on non touch devices?

if (!ScrollTrigger.isTouch) {
  const smoothScroll = ScrollSmoother.create({
   smooth: 1
  })
}


🦜 also I like those birds. 🦩
 

Link to comment
Share on other sites

8 minutes ago, Cassie said:

I'm a little confused now. The issue is on chrome on desktop now? Not on mobile? Can you break this down again for me - just let me know exactly what the issue is and how to recreate? (sorry)

Also if mobile is the issue and you're not using ScrollSmoother for normalize scroll, or effects or smoothing, maybe only create it on non touch devices?

if (!ScrollTrigger.isTouch) {
  const smoothScroll = ScrollSmoother.create({
   smooth: 1
  })
}


🦜 also I like those birds. 🦩
 

Ah sorry! I see that's confusing.
The issue arrises when you view the website in Chrome with devtools and emulate mobile (touch) like the video.
And also when you just go there on mobile (Chrome, possibly other browsers as well).

To recreate (DevTools mobile emulator):
- Open https://zosxos.csb.app/
- Open DevTools, Toggle Device Toolbar (CMD+SHIFT+M), pick iPhone 12 or other device
- Refresh page
- Scroll with "mouse-drag" which is actually a faked touch (like video)

To recreate (Mobile):
- Open https://zosxos.csb.app/
- Scroll

 

  • Like 1
Link to comment
Share on other sites

Ok, So the solution I provided should be good for your use case

https://3q4st8.csb.app/
 

if (!ScrollTrigger.isTouch) {
  const smoothScroll = ScrollSmoother.create({
   smooth: 1
  })
}


We'll look into it though, thanks for the demos!

 

Link to comment
Share on other sites

@merlin any chance you could provide a much simpler reduced test case like in CodePen that isn't dependent on any frameworks? Just some simple colored <div> elements is fine. I couldn't seem to replicate it in a simpler fashion and I wonder if it's somehow related to a ThreeJS rendering cycle issue or a React thing or what(?) I very well may be missing something obvious.

Link to comment
Share on other sites

14 hours ago, Cassie said:

Ok, So the solution I provided should be good for your use case

https://3q4st8.csb.app/
 

if (!ScrollTrigger.isTouch) {
  const smoothScroll = ScrollSmoother.create({
   smooth: 1
  })
}


We'll look into it though, thanks for the demos!

 

Hey Cassie!

Thanks so much for all the help :)
I added this to check behaviour on mobile, but then all scrolltrigger instances (about 6) are overlapping each other (even when having `preventOverlaps` enabled.

 

So it seems like ScrollSmoother also added some type of sorting/layout behaviour?

  • Like 1
Link to comment
Share on other sites

2 hours ago, GreenSock said:

@merlin any chance you could provide a much simpler reduced test case like in CodePen that isn't dependent on any frameworks? Just some simple colored <div> elements is fine. I couldn't seem to replicate it in a simpler fashion and I wonder if it's somehow related to a ThreeJS rendering cycle issue or a React thing or what(?) I very well may be missing something obvious.

Hi Jack!

Hope you're well :)

 

This was the most reduced CSB that I could do with react-three-fiber, just to give a good impression and stay closer to what we're building for our client.

This is a more reduced version: https://codesandbox.io/s/circling-birds-forked-bvnq23?file=/src/App.js

 

I'm adding a video of the unexpected behaviour.

You can see that while scrolling with touch, the pinned container seems to glitch a little up or down (shown as whitespace).

Link to comment
Share on other sites

 

Quote

I added this to check behaviour on mobile, but then all scrolltrigger instances (about 6) are overlapping each other (even when having `preventOverlaps` enabled.

 

So it seems like ScrollSmoother also added some type of sorting/layout behaviour?

Mmm. No there's not any layout/sorting behaviour. Not adding ScrollSmoother on touch devices will just remove smooth scrolling. It shouldn't affect your ScrollTriggers at all.

 

Sanity check - @GreenSock?

Link to comment
Share on other sites

1 minute ago, Cassie said:

 

Mmm. No there's not any layout/sorting behaviour. Not adding ScrollSmoother on touch devices will just remove smooth scrolling. It shouldn't affect your ScrollTriggers at all.

 

Sanity check - @GreenSock?

We use multiple scrollTriggers in different components.
For instance:

  useLayoutEffect(() => {
    if (!ref.current) return;
    const tl = gsap
      .timeline({
        scrollTrigger: {
          trigger: containerRef.current,
          scrub: true,
          start: '-=15%',
          end: `+=40%`,
        },
      })
      .to(ref.current.position, {
        y: -11,
        ease: 'power4.inOut',
      });

    return () => {
      tl.kill();
    };
  }, [ref.current, containerRef]);

When I disable (early return) ScrollSmoother it seems to overlap all the elements with a scrollTrigger binded to them.

But, maybe we need to look at the issue as to why the scrollTriggers end up shocky. If we find something for that, this won't need to be fixed! Since I think the overlapping will be a more complex issue to reproduce?

  • Like 1
Link to comment
Share on other sites

@Cassie @GreenSock
We seem to have a fix.

 

We disable ScrollSmoother on mobile and then add refreshPriority:

 

        refreshPriority: 9,
        preventOverlaps: true,
        anticipatePin: 1,

To the scroll triggers.

 

If I then enable ScrollSmoother, it breaks again. 

So that may be something to look into?

  • Like 2
Link to comment
Share on other sites

Ah interesting - Refresh priority is only really needed when ScrollTriggers are created in the wrong order though. They should be called in the code in the order they execute on the page.

 

I wasn't aware scrollSmoother did anything to 'sort' them (I'll let @GreenSock clear this one up, out of my wheelhouse)

Link to comment
Share on other sites

Ah yeah! Common issue with component stuff where you be certain of running order yourself. That's what refreshPriority is for at the end of the day. Still interested to know why it was working with ScrollSmoother though. 

Did you notice that 3-11 was out too? There are some workarounds for some browser related scroll oddities scroll in there.

Glad the removing on mobile/refreshPriority fix is working for you though.

 

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