Repeating a repeating animation with delay with reanimated
Asked Answered
P

5

6

Using react-native-reanimated, I'm trying to repeat infinitely an animation which is also a repeated animation, with a delay.

With my code, the delay and the nested repeat animation are triggered but not the inifinite one.

Any ideas ?


useEffect(() => {
  progress.value = withRepeat(
   withDelay(2000, withRepeat(withTiming(0, { duration: 500 }), 6, true)),
   -1,
   true
  );
 }, []);

Psychopathy answered 11/7, 2022 at 9:5 Comment(0)
P
1

No solution found with Reanimated, but as suggested by @Abe,a simple setInterval does the trick

 useEffect(() => {
  progress.value = withRepeat(withTiming(0, { duration: 400 }), 6, true);
  const interval = setInterval(() => {
   progress.value = withRepeat(withTiming(0, { duration: 400 }), 6, true);
  }, 6000);
  return () => clearInterval(interval);
 }, []);
Psychopathy answered 15/7, 2022 at 10:2 Comment(0)
C
7

Like @Abe pointed out in his answer, reverse property of withRepeat is not supported when wrapped with other animation modifiers.

But, you can do this without setInterval - making use of withSequence to simulate the `reverse animation

// starting delay of 2000ms
// play animation 6 times
// repeat

progress.value =
withRepeat(
  withDelay(2000, withRepeat(
    withSequence(
      // split duration of 500ms to 250ms
      withTiming(goToValue, {duration: 250, easing: Easing.inOut(Easing.ease)}),
      withTiming(initialValue, {duration: 250, easing: Easing.inOut(Easing.ease)}),
    )
  , 6))
, -1)
Caveat answered 22/10, 2022 at 9:6 Comment(1)
I think the second withRepeat is not necessary.Chela
S
1

You've set the outer withRepeat to 1, so it should only repeat once, is that intended? Use a negative number to repeat indefinitely.

The docs for withRepeat say that withRepeat with the third argument (reverse) set to true doesn't work properly for the withDelay and withSequence animations, that could also be causing an issue. You might want to try reversing the animations manually in a withSequence call and repeating that.

Spickandspan answered 11/7, 2022 at 16:4 Comment(5)
about the withRepeat set to 1, yes it was a typo. I've tried setting withRepeat's third argument to false too, but not working either. I've also tried to repeat a sequence of repeated animation and it's not workingPsychopathy
Does it work without the delay? Does repeating a sequence work? Is there any nested repeat that works for you?Spickandspan
Thanks for your help Abe ! You are right, even the simpliest nested repeat does not work... is it me or do you think its a limitation ? I've tried to ask in the discussion tab of the reanimated github repo but no answer yetPsychopathy
That makes sense, and I think you've done the right thing with posting on the docs. I think if you need an interim solution it could be hacking something together with setInterval.Spickandspan
Yep, setInterval does the job for now !Psychopathy
P
1

No solution found with Reanimated, but as suggested by @Abe,a simple setInterval does the trick

 useEffect(() => {
  progress.value = withRepeat(withTiming(0, { duration: 400 }), 6, true);
  const interval = setInterval(() => {
   progress.value = withRepeat(withTiming(0, { duration: 400 }), 6, true);
  }, 6000);
  return () => clearInterval(interval);
 }, []);
Psychopathy answered 15/7, 2022 at 10:2 Comment(0)
B
1

You can achieve that without setInterval, put withDelay on each animation.

    withRepeat(
      withSequence(
        withDelay(
          2000,
          withTiming(0, {
            duration: 300,
            easing: Easing.inOut(Easing.ease),
          }),
        ),
        withDelay(
          2000,
          withTiming(1, {
            duration: 300,
            easing: Easing.inOut(Easing.ease),
          }),
        ),
      ),
      -1,
    );
Benedix answered 17/2, 2023 at 4:24 Comment(0)
I
-1

You can achieve this by using Animated.sequence This code basically works by re-run the function when the animation done

 function fadeAnimation() {
    Animated.sequence([
      Animated.timing(progress.value, {
        toValue: 0,
        duration: 500,
        delay: 1000,
        useNativeDriver: true,
      }),
      Animated.timing(progress.value, {
        toValue: 1,
        duration: 500,
        useNativeDriver: true,
      }),
    ]).start(() => {
        fadeAnimation();
    });
  }

    useEffect(() => {
        fadeAnimation()
    }, []);
Iconoclasm answered 11/7, 2022 at 9:44 Comment(1)
This solution uses the React Native built-in Animated library, the original question is about ReanimatedSpickandspan

© 2022 - 2024 — McMap. All rights reserved.