Reputation: 30344
I'm totally new to animations in react-native
and I'm trying to create an animated pulsating button using the react-native-reanimated
library.
Animation concepts are really not that clear for me yet but by modifying someone else code, I got pretty close to what I want to create.
I would like to make this pulsating animation continuous. Currently, it pulsates and then stops. I'd appreciate some help with this. I'm including both the code and the snack for you to see a running sample. Please keep in mind that I simply modified someone else's code so I'm sure there are things in this code that are NOT necessary. I'm learning as I work on this button.
Here's a link to the snack: https://snack.expo.io/@imsam67/reanimated-test
And here's the code:
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import Animated from 'react-native-reanimated';
const {
divide,
set,
cond,
startClock,
stopClock,
clockRunning,
block,
spring,
debug,
Value,
Clock,
} = Animated;
function runSpring(clock, value, dest) {
const state = {
finished: new Value(0),
velocity: new Value(0),
position: new Value(0),
time: new Value(0),
};
const config = {
toValue: new Value(0),
damping: 10,
mass: 5,
stiffness: 101.6,
overshootClamping: false,
restSpeedThreshold: 0.001,
restDisplacementThreshold: 0.001,
};
return block([
cond(clockRunning(clock), 0, [
set(state.finished, 0),
set(state.time, 0),
set(state.position, value),
set(state.velocity, -2500),
set(config.toValue, dest),
startClock(clock),
]),
spring(clock, state, config),
cond(state.finished, debug('stop clock', stopClock(clock))),
state.position,
]);
}
export default class Example extends Component {
constructor(props) {
super(props);
const clock = new Clock();
this._trans = runSpring(clock, 10, 150);
}
componentDidMount() {}
render() {
return (
<View style={styles.container}>
<Animated.View
style={[styles.circle, { borderWidth: divide(this._trans, 5) }]}>
</Animated.View>
</View>
);
}
}
const BOX_SIZE = 100;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black',
},
circle: {
backgroundColor: "white",
borderColor: "red",
borderRadius: 150,
height: 150,
width: 150
}
});
Upvotes: 2
Views: 4436
Reputation: 173
Another way to do it a bit more controlled with reanimated 1.x.x is:
const [clock] = useState(() => new Clock());
const loopingValue = useMemo(() => {
const state = {
finished: new Value(0),
position: new Value(0),
time: new Value(0),
frameTime: new Value(0),
};
const config = {
duration: new Value(2000),
toValue: new Value(1),
easing: Easing.linear,
};
const value = block([
// start right away
startClock(clock),
// process your state
timing(clock, state, config),
// when over (processed by timing at the end)
cond(state.finished, [
// we stop
stopClock(clock),
// set flag ready to be restarted
set(state.finished, 0),
// same value as the initial defined in the state creation
set(state.position, 0),
// very important to reset this ones !!! as mentioned in the doc about timing is saying
set(state.time, 0),
set(state.frameTime, 0),
// and we restart
startClock(clock),
]),
state.position,
]);
return interpolate(value, {
inputRange: [0, 0.5, 1],
outputRange: [0, 1, 0],
});
}, [clock]);
A lot of this code is copied from a github thread here: https://github.com/software-mansion/react-native-reanimated/issues/162
Upvotes: 0
Reputation: 6662
A quick way to get this animation to loop is to set the damping to 0. This will keep the spring animation going indefinitely.
const config = {
toValue: new Value(0),
damping: 0, // changed to 0
mass: 5
stiffness: 101.6,
overshootClamping: false,
restSpeedThreshold: 0.001,
restDisplacementThreshold: 0.001,
};
But you would want to change the borderWidth
style to divide by a larger number to keep the border radius from overshooting.
<Animated.View
style={[styles.circle, { borderWidth: divide(this._trans, 25) }]}>
</Animated.View>
You can find the modified Snack here.
For a repeating animtion like this, you could also look at using Lottie, which is much simpler to implement, but less flexible.
Also, you could look at using loop from react native Animations which should allow you to set the border radius.
Upvotes: 2