React Native: How do you animate the rotation of an Image?
Asked Answered
I

6

85

Rotation is a style transform and in RN, you can rotate things like this

  render() {
    return (
      <View style={{transform:[{rotate: '10 deg'}]}}>
        <Image source={require('./logo.png')} />
      </View>
    );
  }

However, to animate things in RN, you have to use numbers, not strings. Can you still animate transforms in RN or do I have to come up with some kind of sprite sheet and change the Image src at some fps?

Iphigeniah answered 25/5, 2016 at 18:34 Comment(0)
N
217

You can actually animate strings using the interpolate method. interpolate takes a range of values, typically 0 to 1 works well for most things, and interpolates them into a range of values (these could be strings, numbers, even functions that return a value).

What you would do is take an existing Animated value and pass it through the interpolate function like this:

spinValue = new Animated.Value(0);

// First set up animation 
Animated.timing(
    this.spinValue,
  {
    toValue: 1,
    duration: 3000,
    easing: Easing.linear, // Easing is an additional import from react-native
    useNativeDriver: true  // To make use of native driver for performance
  }
).start()

// Next, interpolate beginning and end values (in this case 0 and 1)
const spin = this.spinValue.interpolate({
  inputRange: [0, 1],
  outputRange: ['0deg', '360deg']
})

Then use it in your component like this:

<Animated.Image
  style={{transform: [{rotate: spin}] }}
  source={{uri: 'somesource.png'}} />

In case if you want to do the rotation in loop, then add the Animated.timing in the Animated.loop

Animated.loop(
 Animated.timing(
   this.spinValue,
   {
    toValue: 1,
    duration: 3000,
    easing: Easing.linear,
    useNativeDriver: true
   }
 )
).start();
Natascha answered 25/5, 2016 at 19:22 Comment(9)
Nice! Simple and straight to the point! Also, in your rnplay example, how did you know start() could take a callback? Can't seem to find the docs for that on Facebook's RN website.Iphigeniah
Ah, yeah. I think I remember seeing browniefed (Jason Brown) post something about it. It does indeed take a callback though that gets fired when the animation completes. Check out github.com/browniefed/react-native-animation-book , and rnplay.org/browniefed . He's done a lot of examples with animations. I'm glad this helped :)Natascha
remember this.state = { spinValue: new Animated.Value(0) }Concretize
Created an example gist for this: gist.github.com/levynir/5962de39879a0b8eb1a2fd77ccedb2d8Sermonize
Do use loop for making it loop infinitely Animated.loop( Animated.timing(this.spinValue, { toValue: 1, duration: 1000, easing: Easing.linear, useNativeDriver: true, }) ).start()Margerymarget
Guys in this example we are rotating a image can we rotate custom html drawing of our own? For example i want to create a spinner in html and css and i want to rotate it using react native? Any ideas!Bookbindery
Great! if I rotate 180deg, how can I rotate back ?Incompletion
@Incompletion Start an animation that animates the value back to its initial valueAtkins
Just wanted to point out, it is more readable to have the input range be equal to the output range. IE inputRange: [0, 360] and outputRange: ['0deg', '360deg']Atkins
Y
47

Don't forget to add property useNativeDriver to ensure that you get the best performance out of this animation:

// First set up animation 
Animated.timing(
    this.state.spinValue,
  {
    toValue: 1,
    duration: 3000,
    easing: Easing.linear,
    useNativeDriver: true
  }
).start();
Yen answered 16/6, 2017 at 17:21 Comment(0)
F
7

A note for the newbies like me: For animating something else you need to wrap it in <Animated.SOMETHING> for this to work. Or else the compiler will panic on that transform property:

import {Animated} from 'react-native';
...
//animation code above
...
<Animated.View style={{transform: [{rotate: spinValue}] }} >
   <YourComponent />
</Animated.View>

BUT for an image (Animated.Image), the example above is 100% goodness and correct.

Footstep answered 24/12, 2020 at 18:44 Comment(0)
G
2

Just gonna drop the solution I solved by stitching together parts from the answers here.

enter image description here

import { Feather } from '@expo/vector-icons'
import * as React from 'react'
import { TextStyle, Animated, Easing } from 'react-native'

import { Colors, FontSize } from '~/constants/Theme'

export const LoadingSpinner = React.memo(
  ({ color = Colors['sand'], size = FontSize['md'] - 1, fadeInDelay = 1000, ...props }: Props) => {
    const fadeInValue = new Animated.Value(0)
    const spinValue = new Animated.Value(0)

    Animated.sequence([
      Animated.delay(fadeInDelay),
      Animated.timing(fadeInValue, {
        toValue: 1,
        duration: 1500,
        easing: Easing.linear,
        useNativeDriver: true,
      }),
    ]).start()

    Animated.loop(
      Animated.timing(spinValue, {
        toValue: 360,
        duration: 300000,
        easing: Easing.linear,
        useNativeDriver: true,
      })
    ).start()

    return (
      <Animated.View
        style={{
          opacity: fadeInValue,
          transform: [{ rotate: spinValue }],
        }}
      >
        <Feather
          name="loader"
          size={size}
          style={{
            color,
            alignSelf: 'center',
          }}
          {...props.featherProps}
        />
      </Animated.View>
    )
  }
)

type Props = {
  color?: TextStyle['color']
  size?: number
  featherProps?: Partial<Omit<React.ComponentProps<typeof Feather>, 'style'>>
  fadeInDelay?: number
}

Hope it helps 👍

Glindaglinka answered 19/10, 2022 at 9:33 Comment(0)
S
1

Since most of the answers are functions & hooks based, herewith a complete example of class based Animation of Image.

import React from 'react';
import {
  SafeAreaView,
  View,
  Animated,
  Easing,
  TouchableHighlight,
  Text,
} from 'react-native';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      rotateValueHolder: new Animated.Value(0)
    };
  }
  componentDidMount = () => {
    this.startImageRotateFunction();
  }
  startImageRotateFunction = () => {
    Animated.loop(Animated.timing(this.state.rotateValueHolder, {
      toValue: 1,
      duration: 3000,
      easing: Easing.linear,
      useNativeDriver: false,
    })).start();
  };

render(){
    return(
      <SafeAreaView>
        <View>
          <Animated.Image
            style={{
              width: 200,
              height: 200,
              alignSelf:"center",
              transform:
                [
                  {
                    rotate: this.state.rotateValueHolder.interpolate(
                        {
                          inputRange: [0, 1],
                          outputRange: ['0deg', '360deg'],
                        }
                      )
                  }
                ],
            }}
              source={{uri:'https://raw.githubusercontent.com/AboutReact/sampleresource/master/old_logo.png',}}
          />
          <TouchableHighlight
            onPress={() => this.startImageRotateFunction()}>
            <Text style={{textAlign:"center"}}>
              CLICK HERE
            </Text>
          </TouchableHighlight>
        </View>
      </SafeAreaView>
    );
  }
}
Sprit answered 20/12, 2021 at 18:26 Comment(0)
B
1

If you're looking for a spinner, just use ReactNative's built-in <ActivityIndicator />!

import { ActivityIndicator, Text } from 'react-native';

<Text>
  Loading... <ActivityIndicator />
</Text>
Blockish answered 25/10, 2023 at 3:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.