React Native:如何为图像的旋转设置动画?

问题描述 投票:0回答:6

旋转是一种样式变换,在 RN 中,你可以像这样旋转东西

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

但是,要在 RN 中制作动画,您必须使用数字,而不是字符串。你还能在 RN 中制作动画变换吗?还是我必须想出某种精灵表并以某个 fps 更改图像 src?

javascript react-native animation rotation transform
6个回答
213
投票

您实际上可以使用

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();

47
投票

不要忘记添加属性 useNativeDriver 以确保您从该动画中获得最佳性能:

// First set up animation 
Animated.timing(
    this.state.spinValue,
  {
    toValue: 1,
    duration: 3000,
    easing: Easing.linear,
    useNativeDriver: true
  }
).start();

8
投票

给像我这样的新手的注意事项: 要制作其他动画,您需要将其包裹在 中才能正常工作。否则编译器会对该转换属性感到恐慌:

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

但是对于图像(Animated.Image)来说,上面的例子是 100% 好的并且是正确的。


2
投票

只需放弃我通过将此处答案中的各个部分拼接在一起解决的解决方案。

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
}

希望有帮助👍


1
投票

由于大多数答案都是基于

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>
    );
  }
}

0
投票

如果您正在寻找旋转器,只需使用 ReactNative 的内置

<ActivityIndicator />

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

<Text>
  Loading... <ActivityIndicator />
</Text>
© www.soinside.com 2019 - 2024. All rights reserved.