critbob Posted June 26, 2021 Share Posted June 26, 2021 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 More sharing options...
Solution OSUblake Posted June 27, 2021 Solution Share Posted June 27, 2021 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(...); } } 2 Link to comment Share on other sites More sharing options...
Cassie Posted June 27, 2021 Share Posted June 27, 2021 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 More sharing options...
OSUblake Posted June 27, 2021 Share Posted June 27, 2021 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. 2 Link to comment Share on other sites More sharing options...
critbob Posted June 27, 2021 Author Share Posted June 27, 2021 @OSUblake Seems like a great solution, thanks so much for responding! 1 Link to comment Share on other sites More sharing options...
Cassie Posted June 27, 2021 Share Posted June 27, 2021 An event bus! Cool, I like this. Link to comment Share on other sites More sharing options...
critbob Posted June 27, 2021 Author Share Posted June 27, 2021 @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 More sharing options...
OSUblake Posted June 28, 2021 Share Posted June 28, 2021 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 More sharing options...
OSUblake Posted June 28, 2021 Share Posted June 28, 2021 Alright, here's a very simple demo. You can structure however you want, and even use different buses for different things. You're not limited to just 1 bus. I usually make all my plugins a separate bus. https://codesandbox.io/s/black-dew-wrexq?file=/src/App.vue 2 Link to comment Share on other sites More sharing options...
critbob Posted June 28, 2021 Author Share Posted June 28, 2021 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 More sharing options...
OSUblake Posted June 28, 2021 Share Posted June 28, 2021 You wouldn't use this.data. Just this. tl.to(this, { percent: 1, duration: 1, ease: 'power2.in' }, '-=1') 1 Link to comment Share on other sites More sharing options...
critbob Posted June 28, 2021 Author Share Posted June 28, 2021 @OSUblake Superhero for a reason, thanks again man! 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