How To Create a Rotation Animation In React Native

In this tutorial, I’ll show you how to create a button that rotates 720 degrees when it’s pressed. We will be using the React Native Animated animation system to create the rotation animation.

Creating the component

First, we create the functional component ButtonWithSpin that has a TouchableOpacity component with some text inside.

<span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> (</span></span>
<span><span style="color: var(--shiki-color-text)">  &lt;</span><span style="color: var(--shiki-token-constant)">TouchableOpacity</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-function)">onPress</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)">{</span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">handleAnimation</span><span style="color: var(--shiki-color-text)">()}</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-function)">style</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)">{{ width</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">60</span><span style="color: var(--shiki-color-text)"> }}</span></span>
<span><span style="color: var(--shiki-color-text)">  &gt;</span></span>
<span><span style="color: var(--shiki-color-text)">    &lt;</span><span style="color: var(--shiki-token-constant)">Animated.Text</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">style</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)">{animatedStyle}&gt;Click me&lt;/</span><span style="color: var(--shiki-token-constant)">Animated.Text</span><span style="color: var(--shiki-color-text)">&gt;</span></span>
<span><span style="color: var(--shiki-color-text)">  &lt;/</span><span style="color: var(--shiki-token-constant)">TouchableOpacity</span><span style="color: var(--shiki-color-text)">&gt;</span></span>
<span><span style="color: var(--shiki-color-text)">);</span></span>
<span></span>

Notice that the text is created using the Animated.Text component. This is because the text that is going to rotate has to be animatable. If you are rotating something else, then you can use any of these components as well:

We also use the useState Hook to store our rotateAnimation value. This is an animation value from the Animated library. We use `new Animated.Value(0) to initialize the value.

The handleAnimation function

<span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">handleAnimation</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-constant)">Animated</span><span style="color: var(--shiki-token-function)">.timing</span><span style="color: var(--shiki-color-text)">(rotateAnimation</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    toValue</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    duration</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">800</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  })</span><span style="color: var(--shiki-token-function)">.start</span><span style="color: var(--shiki-color-text)">(() </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-constant)">rotateAnimation</span><span style="color: var(--shiki-token-function)">.setValue</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">  });</span></span>
<span><span style="color: var(--shiki-color-text)">};</span></span>
<span></span>

Animated.timing() animates a value over time using easing functions. By default, it uses the easeInOut curve which is perfect for what we are making. We pass our rotateAnimation value and a config value, where we set the duration to be 800ms. The animation is started by calling start(), and we include a callback function that resets the animation.

Interpolate

The interpolate() method maps input ranges to output ranges. A basic mapping to convert a 0–1 range to a 0–100 range would be:

<span><span style="color: var(--shiki-token-constant)">value</span><span style="color: var(--shiki-token-function)">.interpolate</span><span style="color: var(--shiki-color-text)">({</span></span>
<span><span style="color: var(--shiki-color-text)">  inputRange</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  outputRange</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">100</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">});</span></span>
<span></span>

You can also use the `interpolate() method to map out strings. Since we want to rotate our text from 0 degrees to 720 degrees, our code will look like this:

<span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">interpolateRotating</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">rotateAnimation</span><span style="color: var(--shiki-token-function)">.interpolate</span><span style="color: var(--shiki-color-text)">({</span></span>
<span><span style="color: var(--shiki-color-text)">  inputRange</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  outputRange</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">&quot;0deg&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;720deg&quot;</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">});</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">animatedStyle</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  transform</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">    {</span></span>
<span><span style="color: var(--shiki-color-text)">      rotate</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> interpolateRotating</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  ]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">};</span></span>
<span></span>

We also created the animatedStyle object, which includes an array transform with the rotate value interpolateRotating that we just created.

Putting everything together

Add the animatedStyle object to the Animated.Text component and a width to the TouchableOpacity component and we are done!

Button spinning after click

<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> React</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> { useState } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;react&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> { TouchableOpacity</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> Animated } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;react-native&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">ButtonWithSpin</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-constant)">rotateAnimation</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">setRotateAnimation</span><span style="color: var(--shiki-color-text)">] </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">useState</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-keyword)">new</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">Animated</span><span style="color: var(--shiki-token-function)">.Value</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-color-text)">));</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">handleAnimation</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-constant)">Animated</span><span style="color: var(--shiki-token-function)">.timing</span><span style="color: var(--shiki-color-text)">(rotateAnimation</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      toValue</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      duration</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">800</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    })</span><span style="color: var(--shiki-token-function)">.start</span><span style="color: var(--shiki-color-text)">(() </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-constant)">rotateAnimation</span><span style="color: var(--shiki-token-function)">.setValue</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">    });</span></span>
<span><span style="color: var(--shiki-color-text)">  };</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">interpolateRotating</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">rotateAnimation</span><span style="color: var(--shiki-token-function)">.interpolate</span><span style="color: var(--shiki-color-text)">({</span></span>
<span><span style="color: var(--shiki-color-text)">    inputRange</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    outputRange</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">&quot;0deg&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;720deg&quot;</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  });</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">animatedStyle</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    transform</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">      {</span></span>
<span><span style="color: var(--shiki-color-text)">        rotate</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> interpolateRotating</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    ]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  };</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> (</span></span>
<span><span style="color: var(--shiki-color-text)">    &lt;</span><span style="color: var(--shiki-token-constant)">TouchableOpacity</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">onPress</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)">{</span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">handleAnimation</span><span style="color: var(--shiki-color-text)">()}</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">style</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)">{{ width</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">60</span><span style="color: var(--shiki-color-text)"> }}</span></span>
<span><span style="color: var(--shiki-color-text)">    &gt;</span></span>
<span><span style="color: var(--shiki-color-text)">      &lt;</span><span style="color: var(--shiki-token-constant)">Animated.Text</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">style</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)">{animatedStyle}&gt;Click me&lt;/</span><span style="color: var(--shiki-token-constant)">Animated.Text</span><span style="color: var(--shiki-color-text)">&gt;</span></span>
<span><span style="color: var(--shiki-color-text)">    &lt;/</span><span style="color: var(--shiki-token-constant)">TouchableOpacity</span><span style="color: var(--shiki-color-text)">&gt;</span></span>
<span><span style="color: var(--shiki-color-text)">  );</span></span>
<span><span style="color: var(--shiki-color-text)">};</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">default</span><span style="color: var(--shiki-color-text)"> ButtonWithSpin;</span></span>
<span></span>

And there we have it. I hope you have found this useful.