Build Speedometer with React Native Animation

pallavi
4 min readJul 22, 2020

Animation in mobile app enhances the user experience. It provides a perfect visual hint and makes it appealing to the user.

In this post, we will learn how to implement a speedometer animation using React Native Animated API. We will make use of interpolator and rotate animation.

Ground Rules

Before we begin, let us understand the basic rules that we need to follow while using interpolation. If you are already aware of these, feel free to skip to the next section

  • The values in inputRange need not necessarily start at 0. inputRange: [-1 0 , 1] is an valid range.
  • The values in the inputRange always are in increasing order. Otherwise, you will get an error as “Invariant Violation: Input Range must be monotonically non-decreasing
  • Values in outputRange can be in any order unlike values in inputRange. But inputRange and outputRange must be of the same length. Following is the snippet from “react-native” Animated API that validates the same.
AnimatedInterpolation.js
ReactNative/Animated/AnimatedInterpolation.js
  • While interpolating colors, the values must be in RGB/A or HSL color. Hex is not supported. So if you want to animate a color you’ll need to convert your hex to one of the formats interpolation allows.

Interpolation

As per docs, an interpolation maps input ranges to output ranges, typically using a linear interpolation but also supports easing functions.

The inputRange looks at the Animated.Value(val) and then determines how it should be interpreted to the output range.
Here are the inputRange and outputRange we will be using

inputRange  : [ -3, -2, -1, 1, 2, 3]  
outputRange : ['-100deg','-60deg','-20deg', '20deg', '60deg', '100deg']

For every value in inputRange there should be an equivalent value in outputRange.

Input Value and its equivalent output value

Interpolation estimates unknown values that fall between known values which we pass as an inputRange.

Let say if we start our animation with value 0 even if it does not exist in the inputRange that we have provided, interpolation algorithm will use the known values from inputRange and calculate the rotation angle at which out Indicator svg should be at, (0 deg) as shown below:

SVG
We will be using two SVG images, one for “Speedometer” and the other one as “Indicator” on which we will perform rotate animations. Since the “Indicator” SVG we are using is upright 90deg, our initial angle is negative(-ve). The SVG you are using will determine the interpolation rotation angles.

SVG in React Native React Native doesn’t support SVG out of the box. We will use react-native-svg which provides SVG support on React Native. To use SVG images as any other UI components like Button, Text, etc, we will use SVGR tool.

Code
We initialized Animated.Value() with -3, this means the initial rotation angle at which our “Indicator” is placed will be -100deg and it will be our starting position.

state = { value : new Animated.Value(-3)};

Interpolation will start with the initial value provided above

const animInterpolation = this.state.value.interpolate({       inputRange : [ -3, -2, -1, 1, 2, 3],    
outputRange: ['-100deg','-60deg','-20deg', '20deg', '60deg', '100deg']});

Pass the interpolation to rotate

<Animated.View style={{transform:[{rotate:animInterpolation}],position:"absolute", top:40, }}>
<Indicator/>
</Animated.View>

Along with this, I am also interpolating the background colors of a container view. This is totally optional

const colorInterpolation = this.state.value.interpolate({       inputRange: [ -3, -2, -1, 1, 2, 3],   outputRange : ["rgba(255,255,255, 0.9)", "rgba(68, 196, 161, 1)", "rgba(228, 233, 237, 1)", "rgba(52, 152, 219, 1)","rgba(250, 216,   89, 1)", "rgba(192, 57, 43, 1)"]
});

Setting the interpolation on backgroundColor of the container view.

<Animated.View style={[{ backgroundColor:colorInterpolation}, {width:"100%", height:"100%",justifyContent:"center", alignItems:"center"}]}>

Final Result

Github Project

--

--

pallavi

Engineering Manager| Developer | Baking enthusiast