Home > front end >  TransitionGroup lag when using requestAnimationFrame
TransitionGroup lag when using requestAnimationFrame

Time:11-03

Description

I'm creating the following app logic:

  • There is a list of checkable items with a specific price for each.
  • There is a calculated total price for checked items.

I'm also animating the number change for the total price using the requestAnimationFrame. So far so good, the number animation itself works fine.

Problem

However, my TransitionGroup move transition starts to lag when I have the following element structure:

<Transition>
  <div>
    {{ animatedNumber }}
    <TransitionGroup>
      ...
    </TransitionGroup>
  </div>
</Transition>

Notes

  • Seems that there is some conflict between the Transition elements and requestAnimationFrame.
  • The TransitionGroup move animation works fine if I remove the parent Transition element.
  • The TransitionGroup move animation works fine if I remove the number counter based on requestAnimationFrame.
  • This issue happens only on Chrome.

Demo

enter image description here

Zooming into a task you will see:

enter image description here

As we can see each task is caused by the componentUpdateFn. That is because, in every animation frame, you update the variable and force Vue to re-render the template. It's too much work. To make your animation smooth, each animation frame should run in a 16ms time frame (60fps)

To solve your problem you should put in less work as possible in each animation frame by:

  • optimizing your animate function
  • if you want to update your view in every frame, you should do it by pure JS instead of using Vue

This is the optimal version of your code. I just use JS to update the animating number. It's not perfect but it much better than the original version.

// in the script. update the view by pure JS
watch(animatedTotalPrice, () => {
  totalPriceElm.value.innerText = animatedTotalPrice.value;
});
// in the template, DON'T let Vue do the updating work
<h3 ref="totalPriceElm" v-once>{{ animatedTotalPrice }} USD</h3>
  • Related