Search code examples
vue.jsanimationvuexgsap

Problem with toggling a GSAP animation in a watcher that is watching vuex state


I am trying to toggle an animation of an inline svg, as soon as a certain state retrieved from from vuex store changed. To do so I watch the state with a watcher and depending in the state I play the animation forward or backward. This works well, except after the first load of the app. When the watcher notices the change of the state the first time the svg jumps to the new position instead of animating. The second and all further toggles work well and animate smoothly. What am I missing?

Exemplary code:

<template>
  <div class="example">
    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none" aria-labelledby="menu" role="presentation">
      <line ref="top" x1="28" y1="18" x2="28" :y2="18"  stroke-width="2" stroke="currentColor"/>
    </svg>
</div>
</template>

<script>
import { mapState } from 'vuex' 
import { TimelineLite} from 'gsap'
export default {
  name: 'AnimatedIconExample',
  computed: {
    ...mapState({
        isActive: state => state.ui.isActive
    })
  },
  data: function(){
    return {
      timeline: new TimelineLite()
   },
  }
},
  watch: {
    isActive(newValue, oldValue){
        if(newValue){
          this.timeline.to( this.$refs.top, 0.3, { attr: {x1: 10, y1: 18, x2: 25, y2: 18 }})
          this.timeline.play()
        }else{
          this.timeline.reverse()
        }
     }
 }

Solution

  • I finally solved it by adding a tween to the initial state to the mounted() hook.

      mounted(){
        this.timeline.to( this.$refs.top, 0.3, { attr: {x1: 28, y1: 18, x2: 28, y2: 18 }})
    }