Animated.spring finish event - react-native

I am trying to figure out when the Animated.spring event has completed so I can update some state.
I have tried this, but finish throws an undefined error here;
Animated.spring(
this.state.pan,
{ toValue: { x: 0, y: -500 } }
).start().finish(
this.setState({
carousel: false, hasNotification: false
})
);
Any other methods for dealing with this?
Thanks

According to the documentation
start takes a completion callback that will be called when the animation is done. If the animation is done because it finished running normally, the completion callback will be invoked with {finished: true}, but if the animation is done because stop was called on it before it could finish (e.g. because it was interrupted by a gesture or another animation), then it will receive {finished: false}.
So I think this should work:
Animated.spring(this.state.pan, { toValue: { x: 0, y: -500 } }).start(()=>{
this.setState({
carousel: false, hasNotification: false
})
});

You can pass an optional callback:
Animated.spring(
this.state.pan,
{ toValue: { x: 0, y: -500 } }
).start(this.stopAnimation.bind(this))
stopAnimation()
{
this.setState({
carousel: false, hasNotification: false
})
}

Related

Repeating a repeating animation with delay with reanimated

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
);
}, []);
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)
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.
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);
}, []);
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,
);
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()
}, []);

React Native (Animations and setState)

I am facing a particular issue related to react native animations with setState (functional component), I have a countdown made with setInterval and each second I make a setState, whenever I have a setState the animation resets and restarts and I don't know why, I am using also useRef like this
const opacity = new Animated.Value(0) const animatedValueRef = useRef(opacity), the animations is looping like this (each 250millis)
Animated.timing(animatedValueRef.current, {
toValue: 1,
duration: 220,
easing: Easing.ease,
useNativeDriver: true,
}).start((event) => {
if(event.finished) {
opacity.setValue(0);
second();
}
});
}
Thank you!
Edit: this is how I implemented the countdown:
function step1(max, onoff) {
let intervalId;
let varCounter = 1;
setAnimation(true); //animation starts
irrigation(); //animation call
let counter = function () {
if (varCounter < max) {
varCounter= varCounter + 1;
setCounter(varCounter + " " + onoff)
} else {
clearInterval(intervalId);
setCounter(" ");
setAnimation(false);
}
};
intervalId = setInterval(()=>{counter()}, 1000);
}
(The code needs to be refactored)
Basically your component is re- render every time your component’s state changes.
The component gets the updated state and React decides if it should re-render the component.
By default React re-renders everything all the time.
all you have to do is chain your animation. Your animated value will go from 0 to 1, then the second animation will make the value from 1 to 0. You just need to start the animation again after 1 second in your counter function. I suggest making the useNativeDriver: false. No need to setState at all.
Animated.timing(animatedValueRef.current, {
toValue: 1,
duration: 220,
easing: Easing.ease,
useNativeDriver: true,
}).start(() => {
Animated.timing(animatedValueRef.current, {
toValue: 0,
duration: 220,
easing: Easing.ease,
useNativeDriver: true,
}).start(())
});
}

How to provide callbacks to each animation within a Parallel call

Start method takes a callback to be run when the animation is done. But, if I have multiple animations within a Parallel call and each executes over a different duration, with one start() call on the outer Animated.Parallel() call, how do I provide individual callbacks for each animation within?
Animated.parallel([
Animated.timing(
this.pos,
{
toValue: { x: 146, y: 10 },
duration: 1500,
easing: Easing.ease
}
), // I want to run a different callback here
Animated.timing(
this.pos2,
{
toValue: { x: 146, y: 10 },
duration: 2500,
easing: Easing.quad
}
), // ...and here
]).start(function () {
// code for execution after both animations are finished.
});
I accomplished what I wanted by using a sequence within the parallel call.

React Native Animated Loop start callback

I am struggling with React Native Animations here. The outcome is simple, I have an Animated.Image which I want to spin.
All good, until I want to loop thru the animation for n times and do something when it stops.
I have the following code .
Animated.loop(
Animated.timing(this.state.spin, {
toValue: 360,
duration: 1000,
easing: Easing.linear,
useNativeDriver: true,
}), {
iterations: 3
}
).start(() => {
console.log('done');
});
It spins 3 times as per loop iteration but no callback was fired when animation ends.
Here the Expo which replicates this: https://snack.expo.io/S1PjnfB9-
Try the code below
Animated.loop(
Animated.timing(this.state.spin, {
toValue: 360,
duration: 1000,
easing: Easing.linear,
useNativeDriver: true,
}), {
iterations: 3
}
).start(event => {
if (event.finished) {
console.log('finished');
}
});
I just added a check on the event response.
Hope it helps.
Found the answer.
It seems that if you take out useNativeDriver it works as it should be, and the callback is called.
This is weird...

VelocityJS: use stagger with custom sequence

I'm trying to apply a stagger option to a custom velocity sequence.
In my example, I'm using the sequence from the documentation to simplify.
The sequence
$.Velocity.Sequences.mySequence = function (element, options) {
var duration = options.duration || 750;
$.Velocity.animate(element,
{
translateY: "-=10px",
}, {
delay: duration * 0.033,
duration: duration,
loop: 3,
easing: "easeInOutSine"
});
};
The call (failing)
$("div").velocity('mySequence', { stagger: 200 });
The call (succeeding)
Stagger is occurring when I use any predefined sequence from the UI Pack.
$("div").velocity('callout.bounce', { stagger: 200 });
Live example: http://codepen.io/griable/pen/ncsmC
Thanks in advance for helping