旋转是一种样式变换,在 RN 中,你可以像这样旋转东西
render() {
return (
<View style={{transform:[{rotate: '10 deg'}]}}>
<Image source={require('./logo.png')} />
</View>
);
}
但是,要在 RN 中制作动画,您必须使用数字,而不是字符串。你还能在 RN 中制作动画变换吗?还是我必须想出某种精灵表并以某个 fps 更改图像 src?
您实际上可以使用
interpolate
方法对字符串进行动画处理。 interpolate
接受一系列值,通常 0 到 1 对于大多数情况都适用,并将它们插入到一系列值中(这些值可以是字符串、数字,甚至是返回值的函数)。
您要做的就是获取现有的动画值并将其传递给插值函数,如下所示:
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']
})
然后在你的组件中使用它,如下所示:
<Animated.Image
style={{transform: [{rotate: spin}] }}
source={{uri: 'somesource.png'}} />
如果您想循环旋转,请在
Animated.timing
中添加
Animated.loop
Animated.loop(
Animated.timing(
this.spinValue,
{
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true
}
)
).start();
不要忘记添加属性 useNativeDriver 以确保您从该动画中获得最佳性能:
// First set up animation
Animated.timing(
this.state.spinValue,
{
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true
}
).start();
给像我这样的新手的注意事项:
要制作其他动画,您需要将其包裹在
import {Animated} from 'react-native';
...
//animation code above
...
<Animated.View style={{transform: [{rotate: spinValue}] }} >
<YourComponent />
</Animated.View>
但是对于图像(Animated.Image)来说,上面的例子是 100% 好的并且是正确的。
只需放弃我通过将此处答案中的各个部分拼接在一起解决的解决方案。
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
}
希望有帮助👍
由于大多数答案都是基于
functions
和 hooks
,因此这里有一个基于 class
的图像动画的完整示例。
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>
);
}
}
如果您正在寻找旋转器,只需使用 ReactNative 的内置
<ActivityIndicator />
!
import { ActivityIndicator, Text } from 'react-native';
<Text>
Loading... <ActivityIndicator />
</Text>