juliangarnier / anime

JavaScript animation engine
https://animejs.com
MIT License
50.42k stars 3.68k forks source link

How to run animation on same element but with different text ? #873

Open woshichuanqilz opened 11 months ago

woshichuanqilz commented 11 months ago

I add a animation on an element (lets say) with text 'apple' make the 'apple' fly to the center of the screen. Now I want to make the animation again but with text 'banana'. So My code is

// animation for apple
element.innerText = 'banana'
// animation for banana

But the result is : apple animation not shown, just banana animation. So what is the issue here.

  1. What mechanism only make the 'banana' animation shown here.
  2. And how to do it nicely make different text with same animation
  3. I have to create two different elements with same animation but different text or not?
different55 commented 11 months ago

Would need to see some actual code, but my guess is that your problem is that animations are not blocking. They run immediately. So what's actually happening in your code is.


// set up animation for apple
// before the first frame has even happened, change text to banana
element.innerText = 'banana';
// repeat animation, again before the first frame has even happened
woshichuanqilz commented 11 months ago

Would need to see some actual code, but my guess is that your problem is that animations are not blocking. They run immediately. So what's actually happening in your code is.

// set up animation for apple
// before the first frame has even happened, change text to banana
element.innerText = 'banana';
// repeat animation, again before the first frame has even happened
<h1 class="ml1">
  <span class="text-wrapper">
    <span class="line line1"></span>
    <span class="letters">THURSDAY</span>
    <span class="line line2"></span>
  </span>
</h1>

<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js"></script>
<script>
function anim1(tl){
  tl.add({
      targets: '.ml1 .letter',
      scale: [0.3,2],
      opacity: [0,0.5],
      translateZ: 0,
      easing: "easeOutExpo",
      duration: 600,
      delay: (el, i) => 70 * (i+1)
    });
  tl.add({
      targets: '.ml1 .letter',
      opacity: [0.5,0],
      translateZ: 0,
      easing: "easeOutExpo",
      duration: 600,
      delay: (el, i) => 70 * (i+1)
    }); 
}

 // Wrap every letter in a span
var textWrapper = document.querySelector('.ml1 .letters');
textWrapper.innerHTML = textWrapper.textContent.replace(/\S/g, "<span class='letter'>$&</span>");

var tl = anime.timeline()
anim1(tl);
textWrapper.innerHTML = 'banana';
textWrapper.innerHTML = textWrapper.textContent.replace(/\S/g, "<span class='letter'>$&</span>");
anim1(tl);
</script>

here is the code, just see the animation on banana, the 'apple' just blank

different55 commented 11 months ago

Yep, what I mentioned before is the problem. Animations do not "block," they don't wait to finish before moving on. So your code is doing this:

  1. Wrap every letter in a span
  2. Animates the spans
  3. Before the animation even starts, immediately throw out all the spans and overwrite with "banana," breaking the first animation
  4. Make new spans for "banana"
  5. Animate the new spans

You need to tell your code to wait for the animation to finish before moving on. Anime.js supports either promises or callbacks.