Looping Opacity Animation in React Native

I needed to animate a red dot similar to how a recording light flashes. Kinda like this 👇
CSS Keyframes make it as easy as pie 🥧
@keyframes blink {0% {opacity: 0;}50% {opacity: 1;}100% {opacity: 0;}}.blinking-dot {width: 30px;height: 30px;background: rgba(179, 0, 0, 0.8);border-radius: 15px;animation: blink 1s infinite;}
A blinking dot in React Native requires a little more work. Animations are usually implemented using
react-native-reanimated. With the help of
react-native-redash from William Candillon, who does the Can it
be done in React Native videos on YouTube, animating this blinking dot isn't
that bad. Using the loop() function with the
boomerang
option set to true
, the opacity will bounce back and forth from 0 to 1 🦘
import Svg, { Circle } from 'react-native-svg';import Animated, { Easing } from 'react-native-reanimated';import { loop, mix } from 'react-native-redash';const { set, useCode, Value } = Animated;function BlinkingDot() {const animation = new Value(0);useCode(() =>set(animation,loop({duration: 1000,easing: Easing.inOut(Easing.ease),// the animation goes from 0 to 1 and then// from 1 to 0 in the next cycleboomerang: true,autoStart: true,})),[animation]);// Interpolate the node from 0 to 1 without clampingconst opacity = mix(animation, 0.1, 1);return (<Animated.View style={{ opacity }}><Svg style={styles.circle} viewBox="0 0 100 100"><Circle cx="50" cy="50" r="50" fill={Colors.red} fillOpacity="1" /></Svg></Animated.View>);}
React Native Reanimated uses a declarative API, so it's a lot easier to understand what's going on. Animations are performed in steps, which is very similar to how keyframe animations are executed. This is great because it lowers the barrier of entry for developers getting into React Native.
UPDATE: Reanimated 2
With Reanimated 2, it's much simpler and composable out of the box. We can define the animated opacity by composing
together the higher-order animation functions withTiming
, which returns the animation, and withRepeat
, which takes
in the animation to repeat.
import Svg, { Circle } from 'react-native-svg';import Animated, {Easing,useAnimatedStyle,useSharedValue,withRepeat,withTiming,} from 'react-native-reanimated';function BlinkingDot() {const opacity = useSharedValue(0);// Set the opacity value to animate between 0 and 1opacity.value = withRepeat(withTiming(1, { duration: 1000, easing: Easing.ease }),-1,true);const style = useAnimatedStyle(() => ({ opacity: opacity.value }), []);return (<Animated.View style={style}><Svg style={styles.circle} viewBox="0 0 100 100"><Circle cx="50" cy="50" r="50" fill={Colors.red} fillOpacity="1" /></Svg></Animated.View>);}