How to do series/parallel animation in react-native-reanimated 2?

2k Views Asked by At

I'm looking for the equivalent of Animated.sequence and Animated.parallel from react-native. So far from the docs for v2, I could only see the withSequence function that changes the value of only on value and therefore the style of only one component in series.

What I was looking for was to trigger animations in two different components, either in series or in parallel. For parallel, it seems changing values in statements one after another worked. Correct me if I'm wrong.

  // these will run in parallel
  val1Shared.value = withTiming(50);
  val2Shared.value = withTiming(100);

But for series, I need to have each animation inside a useTiming callback. Which leads to kind of callback hell.

  val1Shared.value = withTiming(50, undefined, () => {
    val2Shared.value = withTiming(100);
  });

Please help with the best practices in achieving this with reanimated 2. Thanks.

1

There are 1 best solutions below

0
On

I think there is no way of doing it like in Animated.

This library requires you to think a different way. If you want you run two animations (each one for a separate view) using interpolation, you can use a single shared value and a sufficient interpolation config.

Let's assume (according to your example) that you have two views you want to animate. The first animation is from 0 to 50, the second one is from 0 to 100.

Let's also assume you're transforming an X axis (I don't know what's your case, but it's going to be very similar) and we count the animation progress from 0 to 1, and both views will animate for the same period of time.

Initialize the shared value:

const animation = useSharedValue(0);

And do sth like this (of your choice):

animated.value = withTiming(1, { duration, easing });

For the first view, your transformation will look like this:

const animatedStyles1 = useAnimatedStyle(
() => ({
  transform: [
    {
      translateX: interpolate(animation.value, [0, 0.5, 1], [0, 50, 50]),
    },
  ],
}),
[mode, rectSize]);

and for the second one, like this:

const animatedStyles2 = useAnimatedStyle(
() => ({
  transform: [
    {
      translateX: interpolate(animation.value, [0, 0.5, 1], [0, 0, 100]),
    },
  ],
}),
[mode, rectSize]);

Now the explanation.

For the first view, we only work for the half of progress from the whole animation, so we from 0 to 0.5 we'll animate from 0 to 50. then, for the reset of the progress we'll stay in the same place (this is called a dead zone), to from 0.5 to 1 value of the progress does not change (50 to 50). Now, for the second view, we wait for the progress to be in half, so from 0 to 0.5 we don't do anything (0 to 0). Then, when the progress is in half, we animate the view from 0 to 150.

In general, that way you can orchestrate the whole thing using just a single shared value.

Here you can find more info about the interpolation. The docs is from the react-native's Animated, but the idea is the same.

Good luck!