Reputation: 42602
In my react-native project, I am trying to have my spinner rotating. My spinner is a SVG component <Spinner />
. It is like this:
import * as React from 'react';
import Svg, {Path} from 'react-native-svg';
function Spinner(props) {
return (
<Svg width={24} height={24} fill="none" {...props}>
<Path
...
/>
</Svg>
);
}
export default Spinner;
Since it is a static SVG element, my plan is to create a component that can have rotating animation & apply it to any screens which needs a loading spinner. So I firstly created a LoadingSpinner
component which is supposed to have the rotation animation with the <Spinner />
:
import React, {Component, useState, useEffect} from 'react';
import {View, Animated, Easing} from 'react-native';
import Spinner from './Spinner';
const LoadingSpinner = () => {
const [spinAnim, setSpinAnim] = useState(new Animated.Value(0));
useEffect(() => {
Animated.loop(
Animated.timing(spinAnim, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true,
}),
).start();
});
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Animated.View>
<Spinner />
</Animated.View>
</View>
);
};
export default LoadingSpinner;
Then, in my screen that needs a rotating spinner I just render the LoadingSpinner
,
import LoadingSpinner from '../component/LoadingSpinner'
...
const MyScreen = () => {
...
return (
<View>
{status==='loading' ? <LoadingSpinner /> : null}
</View>
)
}
When I run my app, I can see the spinner is rendered on the screen but it is not rotating. What am I missing?
Upvotes: 4
Views: 2680
Reputation: 9130
You are correctly calculating the value of spinAnim
(i.e. it gradually changes from 0
to 1
), but you are not using that value anywhere.
You need to connect that calculated value to some style to see the results.
In your case, since you're working with rotation, you want the values to go from 0deg
to 360deg
instead of from 0
to 1
. That can be accomplished using the interpolate
function.
Once you have the rotation value in degrees, you can construct a style object, which will apply that value as transform.rotate
(see animatedStyle
in code below).
Finally, you assign that style object to the <Animated.View>
to connect it all:
import React, {Component, useState, useEffect} from 'react';
import {View, Animated, Easing} from 'react-native';
import Spinner from './Spinner';
const LoadingSpinner = () => {
const [spinAnim, setSpinAnim] = useState(new Animated.Value(0));
const interpolateRotation = spinAnim.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
});
const animatedStyle = {
transform: [
{ rotate: interpolateRotation }
]
}
useEffect(() => {
Animated.loop(
Animated.timing(spinAnim, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
})
).start();
});
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Animated.View style={animatedStyle}>
<Spinner />
</Animated.View>
</View>
);
};
export default LoadingSpinner;
If the object you want to rotate is not centered in the <Animated.View>, you can change the center of rotation by moving the object, rotating it and then moving it back, e.g.:
const animatedStyle = {
transform: [
{ translateX: -50},
{ translateY: -50},
{ rotate: interpolateRotation },
{ translateX: 50},
{ translateY: 50},
],
}
A quick demo of the difference that it makes: rotated around center vs rotated around a different point.
Upvotes: 3