Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
critbob

How should I structure my GSAP animations in vue.js?

Go to solution Solved by OSUblake,

Recommended Posts

I’m having a hard time finding info on the best practice for controlling multiple animations across several Vue components in a single gsap timeline.

Can anyone point me in the right direction on how to structure the code so it’s easily maintainable? Should this be done in state management (vuex)? If so, any ideas on how best to structure it?

 

Example on-page-load animation:
1. Animate data variables in an html canvas in the Canvas.vue component, then…
2. Animate Logo translateY in the Logo.vue component, then…
3. Animate Nav translateY and opacity in Nav.vue component...
4. Etc…

 

Any help is appreciated.

Link to comment
Share on other sites

  • Solution

Hi critbob!

 

There's a lot of ways to do this. If you have a bunch of different components that need to communicate with each other, you could just make a Vue instance. 

 

// bus.js
import Vue from "vue";
export default new Vue({
  data() {
    reuturn {
      ...
    };
  },
  watch: {
    ...
  },
  methods: {
    addAnimation(...) {
    
    }
  }
});
  
// nav.vue
import bus from "./bus";
  
export default {
  
  mounted() {
	bus.addAnimation(...);
  }
}

// logo.vue
import bus from "./bus";
  
export default {
  
  mounted() {
	bus.addAnimation(...);
  }
}

 

  • Like 2
Link to comment
Share on other sites

Wait, this is really interesting and something I've needed to do in the past.

But I'm not sure I completely understand. Where would the timeline be set up? In the bus.js file?

 

Link to comment
Share on other sites

8 hours ago, Cassie said:

But I'm not sure I completely understand. Where would the timeline be set up? In the bus.js file?

 

Yeah, that's kind of what I was trying to get at with the psuedo code. But you could also use it just to store data and fire off events.

https://medium.com/easyread/vue-as-event-bus-life-is-happier-7a04fe5231e1

 

So you could register when something is ready with the bus, and then when all the conditions have been met, you could have the bus fire off an event and create the timeline in one of your components.

 

21 hours ago, critbob said:

Should this be done in state management (vuex)?

 

Vuex is just a Vue instance, just like I showed, but it obviously follows some preset rules. By creating your own Vue instance, you can customize it however you want, and it will be completely reactive.

 

  • Like 2
Link to comment
Share on other sites

@OSUblake Seems like a great solution, thanks so much for responding!

  • Like 1
Link to comment
Share on other sites

An event bus! Cool, I like this.

Link to comment
Share on other sites

@OSUblake So it seems this mostly works. But so far not entirely.

 

I can target template elements from within animationBus by referencing the element's class (or ID).

So this works:

export const animationBus = new Vue({
  methods: {
    addAnimations: () => { // Any simple timeline for proof of concept.
      var tl = gsap.timeline()
      tl.set('.my-class', { opacity: 1 })
      tl.to('.my-class', { opacity: 0, duration: 2, ease: 'slow' }, '+=0.5')
    }
  }
})

 

But I can't target the component's model data directly.

So this doesn't work:

export const animationBus = new Vue({
  methods: {
    addAnimations: () => { // Any simple timeline for proof of concept.
      var tl = gsap.timeline()
      tl.set(this.data, { percent: 1 })
      tl.to(this.data, { percent: 0, duration: 2, ease: 'slow' }, '+=0.5')
    }
  }
})

console.error: TypeError: _this is undefined

 

Am I conceptually on the right track?

 

Ideally I'd like to have the ability to animate both template elements and data elements in the same timeline. Any ideas on how to target the component's data from within the event bus?

 

And for curiosity's sake, since you mentioned that there are a lot of ways to accomplish this, could you reference any other methods that come to mind? (even if it's just a search term for me to google.)

 

Thanks again for the help!

Link to comment
Share on other sites

Not sure what this.data is supposed to refer to, but the addAnimations method should not be an arrow function.

 

The only search term I can suggest is Vue bus, but it's unlikely it's going to bring up anything related to animations. I just used that pattern, and adapted it to fit my needs for animations. I'll make a simple demo on codesandbox for you tomorrow.

 

 

Link to comment
Share on other sites

Sorry for the confusion.

 

For explanation, given a stand-alone vue component like below, I can target both template elements (.my-class) AND the component's data (this.data.percent) :

<template>
  <div class="my-class"> // animate with the first 'to' tween in mounted.
    Lorem ipsum, dolor sit amet...
  </div>
</template>

<script>
export default {
  data () {
    return {
      percent: 0  // animate with the second 'to' tween in mounted.
    }
  },
  mounted () {
    var tl = this.$gsap.timeline()
    tl.to('.my-class', { x: 1, duration: 2, ease: 'slow' }, '+=0.5')
    tl.to(this.data, { percent: 1, duration: 1, ease: 'power2.in' }, '-=1')
  }
}
</script>

 

However in the event bus, I have not found a way to manipulate the component's data (this.data.percent)

 

...

Link to comment
Share on other sites

You wouldn't use this.data. Just this.

 

tl.to(this, { percent: 1, duration: 1, ease: 'power2.in' }, '-=1')

 

 

  • Like 1
Link to comment
Share on other sites

@OSUblake Superhero for a reason, thanks again man!

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