ingram-projects / animxyz

The first truly composable CSS animation library. Built for Vue, React, SCSS, and CSS, AnimXYZ will bring your website to life.
https://animxyz.com
MIT License
2.42k stars 56 forks source link

nested + staggered start the animation of the second parent only when the first has finish ? #16

Closed flapili closed 3 years ago

flapili commented 3 years ago

Hi, I would like to know if there is a possibilty to start the animation of a second parent only when the animation of the parent and their child as finished.

My case is animate each letter of a title but I can't just loop over the title because of the wrap: image in the screen the world "itérateurs" should be wrapped in the next line.

my current code is:

                <XyzTransitionGroup
                  appear
                  xyz="fade small up stagger duration-30"
                >
                  <div
                    v-for="(word, i) in article.title.split(' ')"
                    :key="`title-${i}`"
                    style="display: inline"
                  >
                    <template v-if="i != 0">&nbsp;</template
                    ><span
                      v-for="(char, i2) in word"
                      :key="`title-${i}-${i2}`"
                      class="xyz-nested"
                      :ref="`title-${i}-${i2}`"
                      >{{ char }}</span
                    >
                  </div>
                </XyzTransitionGroup>
milesingrams commented 3 years ago

Hi Flapili! There are two ways to fix this which I have put in the linked CodeSandbox.

Approach 1: Use an XyzTransition component and give each span an xyz-nested class and add an --xyz-index (This is because the default CSS only sets the index for the first 20 elements).

Approach 2: Use an XyzTransitionGroup component wrapping the spans.

https://codesandbox.io/s/animxyz-letters-stagger-example-1rq8b?file=/src/App.vue

milesingrams commented 3 years ago

Let me know if this solves your issue or if you have any additional questions! Thanks for using our library and for helping us improve it.

flapili commented 3 years ago

Hi, unfortunately that doesn't solve the main issue which is the new line in a word image

that why I must have 2 loops: one for the word and a second, nested, for the char in the word.

<span
  v-for="(word, index_word) in article.title.split(' ')"
  :key="index_word"
  style="display: inline-block"
>
  <template v-if="index_word != 0">&nbsp;</template
  ><span
    v-for="(char, index_char) in word"
    :key="`${index_word}-${index_char}`"
    >{{ char === " " ? "&nbsp;" : char }}</span
  >
</span>

the main issue now is compute from article.title, word, index_word, char and index_char the index of the letter in article.title, so I could apply the index to --xyz-index or to --xyz-delay . Any hint about how compute the index ?

Thanks for writing this library 👍

milesingrams commented 3 years ago

You should be able to do this using a computed property? https://vuejs.org/v2/guide/computed.html Basically you can map the title to a nested array where each char is associated with a global index.

Check out the last example in the codesandbox I updated: https://codesandbox.io/s/animxyz-letters-stagger-example-1rq8b?file=/src/App.vue

milesingrams commented 3 years ago

Note that for appear animations only you can do it without an XyzTransition or XyzTransitionGroup component if you want. Those are mostly helpful if the content is dynamic and you want in and out animations as elements are added and removed.