Jump to content
Search Community

ScrollTrigger.refresh() after orientationchange cause pin element to break

BenjaminO test
Moderator Tag

Recommended Posts

Hello 👋,

 

I remarked that my pin elements (created with scrollTrigger), are broken after I rotate my phone (tested with an IPhone 13 IOS 16 on Safari and Firefox). I added the code below (I am awaiting 100ms after orientationchange to trigger a scrolltrigger.refresh()) which is doing the job 90% of the time (still some cases where it is not working). Do you know if there is a more convenient way to wait for the refresh ?

 

  window.removeEventListener('orientationchange', async () => {
    await delay(80)
    ScrollTrigger.refresh()
  })

// Creation of Pin Element
ScrollTrigger.create({
        trigger: Element,
        start: 0,
        pin: true,
        pinSpacing: false,
        anticipatePin: 1,
        endTrigger: '#gridgalerie' // I tried end: 'max' without sucess in my case
      })

 

Link to comment
Share on other sites

I'm not sure why you'd need to wait longer. Very difficult to say without a minimal demo. Do you have things on the page that perhaps take some time to "settle" layout-wise? Perhaps you've got CSS transitions on things? 

 

Maybe try waiting for one or two requestAnimationFrame()s to ensure things have rendered first? (Taking stabs in the dark here) :)

 

  • Like 1
Link to comment
Share on other sites

Hello @GreenSock, my case is a bit complicated to reproduce. I am using ScrollTrigger to pin my elements within a ScrollSmoother instance (I made this choice because of the structure of my code -> using nuxt 3). I am also applying some animation on the pin elements childs which are conditional (I mean the animations) based on a GSAP.matchMedia(). I think it is not linked to GSAP directly but more to my image gallery. I am using vue-masonry-wall (https://github.com/DerYeger/vue-masonry-wall) which is organizing my images nicely with JS. The problem is that the « drawing » step of this plugin can end after the ScrollTrigger event thus changing the height of smooth content 🥲. This plugin emits it’s own custom event when the « drawing » event occurs but I still have to wait a little bit longer after it, so it’s not ideal (equivalent to my first solution). I’ll try to manage it with a nextTick() from vue or with your suggestion : one or two requestAnimationFrame() 🤔 

Link to comment
Share on other sites

@BenjaminO a minimal demo is not your whole (complex) project. it is a dumped down version of the issue. This is a great tool to have in your tool belt as a developer, that you can take a step back and just focus on the issue at hand and make a simple version of this to test out some solution. I find when I make a minimal demo I usually find the issue my self and if not you have something you can share to ask for feedback. 

 

If you're using Nuxt or some other framework, you may find CodeSandbox easier to use. But if there is an issue with GSAP you don't need any frameworks to demonstrate the issue at hand. Again a minimal demo is just some colored divs to illustrate the problem. 

 

Hope you find your solution!

  • Like 3
Link to comment
Share on other sites

Hi,

 

I think the first approach you should try is Vue's Next Tick function, since that is incorporated into the framework and is totally battle tested.

 

Also you mention you're using Nuxt 3, while I love everything Vue-related, is worth noticing that Nuxt 3 is still in release candidate stage, not even beta, so I wouldn't be too surprised that a few things are not in the right place yet. As @mvaneijgen mentions, if you can create a codesandbox we could also port that to Nuxt 2 and see if the issue happens there as well in order to see if something is different when swapping the Nuxt version.

 

Also I'm curious about this:

1 hour ago, BenjaminO said:

I think that maybe scrollTrigger doesn't refresh after orientation change when the page is scrolled at the same time (with ScrollSmoother) 🧐

How can you scroll at the same time you are changing the devices orientation? 🤔 I never been in such situation and also never heard about such way of testing a site. It would be great if you could elaborate a bit more about this.

 

Happy Tweening!

Link to comment
Share on other sites

On 10/14/2022 at 1:45 AM, BenjaminO said:

I am using vue-masonry-wall (https://github.com/DerYeger/vue-masonry-wall) which is organizing my images nicely with JS. The problem is that the « drawing » step of this plugin can end after the ScrollTrigger event thus changing the height of smooth content 🥲. This plugin emits it’s own custom event when the « drawing » event occurs but I still have to wait a little bit longer after it, so it’s not ideal (equivalent to my first solution).

It sounds like you've got a complicated setup with 3rd party tools that may be messing with the layout for a while - the key is to call ScrollTrigger.refresh() AFTER the layout is finalized/settled. 

Link to comment
Share on other sites

Hello @Rodrigo and thank you for your suggestions ! Indeed, I have a complicated and not very stable setup that relies on third party tools 😅 which is not ideal to debug ! And of course I am aware that I have to resfresh scrolltrigger after the layout is finalized @GreenSock 🙂

2 hours ago, Rodrigo said:

I think the first approach you should try is Vue's Next Tick function, since that is incorporated into the framework and is totally battle tested.

I tested this without sucess 😕

  window.addEventListener('orientationchange', async () => {
    await nextTick()
    ScrollTrigger.refresh()
  })
2 hours ago, Rodrigo said:

How can you scroll at the same time you are changing the devices orientation? 🤔 I never been in such situation and also never heard about such way of testing a site. It would be great if you could elaborate a bit more about this.

I tested scrollTrigger refresh event by using the following command :

  ScrollTrigger.addEventListener('refresh', () => console.log('refresh'))

I accessed to the dev tool of my Iphone with my Mac using Safari. When changing orientation of my phone (rotating the screen), it happens sometimes that the refresh event doesn't occurs ! I found out that if I scroll, then I rotate the phone the refresh doesn't fires. However, when waiting for 1/2s without touching the screen then rotating the phone, the event is triggered. I was thinking that maybe there is an interaction between the two but I need to reproduce and isolate the problem to solve it. For now I have no idea of what's going on !

Link to comment
Share on other sites

Are you saying that you manually call ScrollTrigger.refresh() but doing so [sometimes] does NOT result in your "refresh" event handler getting called? If so, yeah, I'd love to see a minimal demo

 

Keep in mind that by default, ScrollTrigger does a "safe" refresh if it's called in the middle of a scroll on a mobile device because refreshing would interfere with the scroll (stop it). That's just how iOS devices work - you lose the momentum scroll in that case. That's why ScrollTrigger waits for the "scrollEnd" event to fire before executing the "refresh" in that particular case. But when you manually call a ScrollTrigger.refresh(), it should force it (not "safe"). 

  • Thanks 1
Link to comment
Share on other sites

I tried both situations : manually triggering refresh + log AND just log. In that second situation only, that's were sometimes scrolltrigger doesn't fires at all 😢

19 minutes ago, GreenSock said:

Keep in mind that by default, ScrollTrigger does a "safe" refresh if it's called in the middle of a scroll on a mobile device because refreshing would interfere with the scroll (stop it). That's just how iOS devices work - you lose the momentum scroll in that case. That's why ScrollTrigger waits for the "scrollEnd" event to fire before executing the "refresh" in that particular case. But when you manually call a ScrollTrigger.refresh(), it should force it (not "safe"). 

I was thinking about that ! The momentum when scrolling on Safari is long enough to block the refresh event after rotating the phone, thus causing the bug. The problem is that even a very small scroll can cause the bug, ruining the UX. What I don't understand, is that the refresh is not called AT ALL sometimes (maybe if it is block too long it is not triggered) ? So, in that situation, I think that the best for me is to trigger it manually without the true parameter. The other problem is that I need to wait that the layout is finalized before refreshing. Apart from delaying manually the refresh, I don't see another way to deal with it as single/double requestAnimationFrame() and nextTick() doesn't seems to work in my case 😅

 

19 minutes ago, GreenSock said:

you lose the momentum scroll in that case

Are you 100% sure about that. When I triggers the refresh manually ,the scroll is blocked very briefly then the screen rotates then the scroll continues which feels quite natural 🧐

Link to comment
Share on other sites

5 minutes ago, BenjaminO said:

The problem is that even a very small scroll can cause the bug, ruining the UX.

I didn't follow that - what exactly "ruins the UX"? You switch orientations and then scroll only a tiny bit and something horrible happens? 

 

6 minutes ago, BenjaminO said:

So, in that situation, I think that the best for me is to trigger it manually without the true parameter. The other problem is that I need to wait that the layout is finalized before refreshing. Apart from delaying manually the refresh, I don't see another way to deal with it as single/double requestAnimationFrame() and nextTick() doesn't seems to work in my case 😅

Yep, sounds like it. Again, I'm totally taking stabs in the dark here since you haven't provided a minimal demo but it does sound like you need to manually call ScrollTrigger.refresh() on orientation change AFTER the layout has settled. 

Link to comment
Share on other sites

37 minutes ago, GreenSock said:

didn't follow that - what exactly "ruins the UX"? You switch orientations and then scroll only a tiny bit and something horrible happens? 

Sorry I wasn't very clear on that 😅 I was saying that even a small scroll + rotating the screen was blocking the refresh event indefinitely so ruining the UX because I am also using ScrollSmoother 😢 thus unpining my elements + creating a giant blank space at the bottom because smooth content height is not updated 🧐

 

EDIT: The complicated thing is that Nuxt 3 doesn't handle really well GSAP (ScrollSmoother particularly). I tried to reproduce my problem with a very simple example but I can't reproduce the problem without incorporating nuxt I think. 

See below :

See the Pen MWGrxze by benjamOD2 (@benjamOD2) on CodePen

 

I think I'll wait for this plugin to be compatible with Nuxt 3 and see if my problem goes away. https://github.com/ivodolenc/nuxt-gsap-module/issues/24

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