Ben Carey Posted January 6, 2021 Share Posted January 6, 2021 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? 1 Link to comment Share on other sites More sharing options...
Ben Carey Posted January 7, 2021 Author Share Posted January 7, 2021 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. 3 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now