Jump to content
Search Community

Issue with ScrollTrigger and Vue JS

Ben Carey test
Moderator Tag

Recommended Posts

I have come across an issue with ScrollTrigger and Vue JS, and whilst I know what is causing it, I cannot think of a solution to the problem...

 

Consider the following two components:

 

Component 1 (in <router-view>)

<template>
  
  <h1 id="heading">Hello World</h1>

</template>

<script>
    
    import { gsap } from 'gsap';
    import { ScrollTrigger } from 'gsap/ScrollTrigger';

    gsap.registerPlugin(ScrollTrigger);

    export default {
      
      mounted() {
        
        const scrollTrigger = {
          trigger: '.some-section',
          start: 'top bottom',
          end: 'bottom bottom',
          scrub: true,
          pin: true
        };
        
        gsap.timeline({ scrollTrigger })
          .from('#heading', { y: 500, opacity: 0 });
      }

    }

</script>

Component 2 (outside of <router-view>)

<template>
  
  <footer id="main-footer">
  	<p>Some footer</p>
  </footer>

</template>

<script>
    
    import { gsap } from 'gsap';
    import { ScrollTrigger } from 'gsap/ScrollTrigger';

    gsap.registerPlugin(ScrollTrigger);

    export default {
      
      mounted() {
        
        const scrollTrigger = {
          trigger: '#main-footer',
          start: 'top bottom',
          end: 'bottom bottom',
          scrub: true
        };
        
        gsap.timeline({ scrollTrigger })
          .from('#main-footer p', { y: 500, opacity: 0 });
      }

    }

</script>

The problem above is that Component 2 gets rendered before Component 1. This causes the triggers to be calculated incorrectly...

 

The usual solution to this would be to utilise refreshPriority, alongside sort and refresh - however, these do not work as each component creates a new instance of ScrollTrigger and therefore, the refreshPriority has no effect.

 

I have tried setting GSAP as a global on the Vue prototype, and importing ScrollTrigger in my app.js file, but this did not solve the issue.

 

For example (did not work):

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

Vue.prototype.$gsap = gsap;

 

Can anyone suggest a way in which I can either, prevent the second component from calling the ScrollTrigger set up until the other components have (not using events as this is dirty), or, is there a way in which I can register one ScrollTrigger instance globally and then all tweens will be added to the same instance?

  • Like 1
Link to comment
Share on other sites

For anyone coming across this issue in the future, I have come up with the following solution:

 

This is inserted into my footer component:

 

watch: {

    $route() {

        // Initialize the scroll animation
        bus.$once('page-ready', this.initializeScrollAnimation);

    }

}

Where page-ready is a custom event that I fire when all assets have been preloaded and the main route has been mounted. This forces the footer to initialise the scroll animation after the router-view components have initialised their scroll animations.

  • Like 3
  • Thanks 1
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...