Jump to content
Search Community

Flip.from() triggers onLeave() while target <div> is still present in Nuxt

Hinterlander test
Moderator Tag

Go to solution Solved by OSUblake,

Recommended Posts

Selecting a list-item works but doesn’t animate, because GSAP thinks that div._selected has left the DOM as onLeave() indicates. It’s still there, but in a new position. The beforeUpdate() and updated() lifecycle hooks are where I'm getting the state and performing the flip.

 

As an aside, the animation works correctly when the List.vue data changes. 🤷‍♂️ Any idea how to approach this?

 

---


Places.vue

<template>
  <list>
    <list-item
      class="place"
      v-for="place in places"
      :key="place.id"
      @click="selectPlace(place)"
      :selected="place.id === $store.state.places.selected_record_id">
      
      <div class="name">{{ place.name }}</div>
    </list-item>
  </list>
</template>
<script>
export default {
  name: 'places-page',
  methods: {
    selectRecord ({ id }) {
      this.selected_record = id;
    }
  }
}
</script>

 

ListItem.vue

<template>
  <li class="_item" @click="$emit('click')">
    
    <slot></slot>
    <!-- This is what moves around -->
    <div class="_selected"
      data-flip-id="selected"
      v-if="selected">
    </div>
  </li>
</template>
<script>
export default {
  name: 'list-item',
  props: {
    selected: { type: Boolean, default: false }
  }
}
</script>

 

List.vue

<template>
  <ul class="list-control">
    <slot></slot>
  </ul>
</template>
<script>
export default {
  name: 'list-control',
  data () {
    return {
      state: null
    };
  },
  beforeUpdate () {
    this.$data.state = Flip.getState(gsap.utils.toArray('.list-control [data-flip-id]'));
  },
  updated () {
    Flip.from(this.$data.state, {
      duration: 0.8,
      ease: 'expo.out',
      simple: true,
      nested: true,
      onEnter: elements => {
        console.log('*** onEnter', elements);
      },
      // When clicking on an item, this thinks that `div._selected`
      // has left the DOM and didn’t come back. Seems like
      // a race condition, but unsure how to proceed since the DOM
      // should be fully `updated` at this point
      onLeave: elements => {
        console.log('*** onLeave', elements);
      }
    });
  }
}
</script>

 

Link to comment
Share on other sites

Absolutely! I've recreated the issue here:

 

https://codesandbox.io/s/gsap-flip-exploration-v92g0

 

So as you can see, sorting the data triggers the Flip animation, but clicking an item does not. The click event triggers Vue's lifecycle hooks beforeUpdate() and updated(), but then it's followed by Flip's onLeave() which causes the animation to be suppressed.

Link to comment
Share on other sites

  • Solution

Thanks for the demo! Is this what you're looking for?

 

https://codesandbox.io/s/gsap-flip-exploration-forked-fe4r8?file=/src/components/TopsyList.vue

 

I just added targets to the Flip.

 

Quote
targets String | Element | Array | NodeList - by default, Flip will use the targets from the state object (first parameter), but you can specify a subset of those as either selector text (".class, #id"), an Element, an Array of Elements, or a NodeList. If any of the targets provided is NOT found in the state object, it will be passed to the onEnter and not included in the flip animation because there's no previous state from which to pull position/size data.

 

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