hypernym-studio / nuxt-gsap

GSAP module for Nuxt.
MIT License
295 stars 12 forks source link

ScrollTrigger and Page Navigation conflicts, .kill . refresh (?) #29

Closed esadrian closed 2 years ago

esadrian commented 2 years ago

Hi, I have been reading a lot of questions in the GSAP Forum about Nuxt page navigation affecting scrollTrigger. They solve it destroying all the tweens with .kill() on the beforeDestroy() hook, which I didn't find any information about on the Nuxt docs nor here and after trying it on my project it gives me page error when navigating to another page. They talk about it here.

export default {
  mounted() {
    this.animateOnScroll()
  },

  methods: {
    animateOnScroll() {
      const gsap = this.$gsap.timeline({
        scrollTrigger: {
          trigger: '.content',
          pin: true,
          end: 'bottom',
          scrub: true
        },
      });
      gsap.from(".box", {
        x: 300,
        opacity: 0,
        stagger: 0.1,
        ease: 'Power1.easeInOut',
      });
    },
  },

  beforeDestroy() {
    this.animateOnScroll.scrollTrigger.kill();
    this.animateOnScroll.kill();
    // or target every scrolltrigger
    scrollTrigger.getAll().forEach((t) => t.kill());
  },
}

The beforeDestroy functions none of them work for me, I'm probably doing something wrong. And in the Animate on scroll examples it is not included, but is it needed to do so? If so, how can I do it (and maybe include it in the docs).


Also, sometimes after navigating, the scrollTrigger trigger may be some pixels above the element itself and here they talk about using ScrollTrigger.refresh() but don't know where to put it neither. P.S: The inject("ScrollTrigger", ScrollTrigger); they talk about is not needed now that it exist this module, right?

So, do we have to create and kill the scrollTrigger every time, refresh it...? It's so confusing hahaha. I know these questions may be a bit perplex, but I can't find the right solution. Thanks :)

ivodolenc commented 2 years ago

Hi, please create a minimal reproduction because it's difficult to understand what's the problem (just kidding it takes to much time to debug it 😂)

Many questions require ready-made solutions, copy paste answers or real support like "How to...". If the package is useful to you, before you ask for help, at least it's nice to leave the star 😉 Just saying

this.animateOnScroll.scrollTrigger.kill()

Also, I see you are adding the GSAP .kill() method to the vue method and that's one of the reasons why this won't work.

P.S: The inject("ScrollTrigger", ScrollTrigger); they talk about is not needed now that it exist this module, right?

I don't understand this part. If you using nuxt-gsap-module just follow docs.

After activation, plugins are automatically registered and available globally, so you won’t have to worry about it (applies to all plugins).

From example above, you need:

// GSAP core
const gsap = this.$gsap

// GSAP timeline
const tl = this.$gsap.timeline

// ScrollTrigger
const ScrollTrigger = this.$ScrollTrigger

Anyway, like I said create a minimal repo so I can easily check what it’s all about.

ivodolenc commented 2 years ago

Simple example with .getById() and .kill() methods:

<template>
  <div>
    <nuxt-link to="/about">About</nuxt-link>
    <section style="height: 150vh"></section>
    <h1 class="title">Nuxt GSAP Module</h1>
    <section style="height: 150vh"></section>
  </div>
</template>

<script>
  export default {
    methods: {
      customScrollTrigger() {
        this.$gsap.to('.title', {
          scrollTrigger: {
            id: 'title01', // Add unique Id
            trigger: '.title',
            start: 'center bottom',
            end: 'center top',
            scrub: true,
            markers: true
          },
          x: 500
        })
      }
    },

    mounted() {
      this.customScrollTrigger()
    },

    beforeDestroy() {
      // Returns the ScrollTrigger with unique Id
      // and kills it before route change
      this.$ScrollTrigger.getById('title01').kill()
    }
  }
</script>
esadrian commented 2 years ago

Hi! I managed to get the beforeDestroy() hook right, thanks a lot for your response, couldn't find the right answer anywhere. Is there a way to select every scrollTrigger and animation to kill it? Something like scrollTrigger.getAll().forEach((t) => t.kill()); that I found earlier.


Second, If you see this example bellow, when you get back to the main page, the first trigger is few pixels bellow its possition. Is this normal? Do I have to add a .refresh or something?

https://codesandbox.io/s/example-for-navigation-dxglh?file=/pages/index.vue

ivodolenc commented 2 years ago

Please read the docs and ask for support on official forums. Closing this because there is no issues with the module.

ivodolenc commented 2 years ago

See comment

woutercouvaras commented 2 years ago

For others that encounter a seemingly similar problem, here's an additional thing to check for (which has cost me HOURS).

I was using $fetch to fetch data and even though I was killing scroll trigger instances, things would only work on the intial page load and not again after that, no matter what I tried.

Try using asyncData, instead of fetch, as it solved what loooked like a weird navigation/state/mem leak related issue for me.