React Native 动画(Animated)

Posted 殇神马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Native 动画(Animated)相关的知识,希望对你有一定的参考价值。

一、前言
对于一个移动应用APP,其中的动画交互能够给用户带来很好的体验,所以动画在移动应用开发过程中是非常重要的;

二、React Native中实现动画的方式

-不断修改state
-Animated API

首先如果不使用任何动画API,那想到的实现动画效果的方式,应该就是通过不断修改state中的组件相关的属性值来实现动画效果,但是这个就是不断的重新渲染整个页面,所以可能会非常影响性能;
React Native中提供了Animated API来实现动画,Animated API可以简洁的实现各种动画和交互方式,并且具备极高的性能;
我们知道所谓动画,无非就是通过平移、缩放、旋转,透明度变换,以及这些基本变换的组合; React Native中也是通过Animated API 来实现对组件透明度style属性(opacity)以及style中transform属性的(translateX,translateY,rotate,scale)的修改来实现平移,缩放,旋转,透明度变换;

三、Animated 动画

-使用Animated 实现动画的步骤

(1)组件需要变化的属性必须使用Animated.Value或者Animated.ValueXY作为值

(2)需要进行动画的组件必须是Animated组件,Animated 提供了
Animated.View,Animated.Image,Animated.Text,Animated.ScrollView, Animated.FlatList, Anmated.SectionList这些基本的动画组件,但是也可以通过Animated.createAnimatedComponent()方法将任意组件变成Animated组件

(3)创建动画
Animated用于创建动画的方法:
Animated.timing():最常用的动画类型,使得值按照过渡曲线随时间变化
Animated.spring():弹簧变化效果
Animated.decay():衰变效果,以一个初始的速度和一个衰减系数逐渐减慢为 0

(4)创建动画之后调用start()方法,stop()方法开启和结束动画
以上就是Animated实现动画的基本步骤

-动画示例
下面我们就按照上面的步骤,来实现透明度,平移,缩放,旋转动画;

透明度动画:

import React from 'react';
import  Animated, Text, View,
Button
 from 'react-native';

export default  class AnimatedViewScreen extends React.Component 
    fadeInOpacity= new Animated.Value(0) //透明度初始值设为0
    componentDidMount() 
        Animated.timing(        //随时间变化而执行动画
            this.fadeInOpacity, //动画中的变量值
            
                toValue: 1, // 透明度最终变为1,即完全不透明
                duration: 3000, //动画时长
            
        ).start(); //开始执行动画
    
    render() 
        return (
            <View style=flex:1,justifyContent:'center',alignItems:'center'>
      <Animated.View style=width:100,height:100,opacity:this.fadeInOpacity>
          <Button title='透明度 按钮'/>
     </Animated.View>  
  </View>
 

平移动画:

import React from 'react';
import  Animated, Text, View,
Button
 from 'react-native';

export default  class AnimatedViewScreen extends React.Component 
    translateX=new Animated.Value(0)
    componentDidMount() 
      Animated.timing(this.translateX,
            
                toValue:150,
                duration:3000,
            
        ).start();
    
    render() 
        return (
            <View style=flex:1,justifyContent:'center',alignItems:'center'>
     <Animated.View style=width:100,height:100,transform:[translateX:this.translateX]>
       <Button title='平移按钮'/>
    </Animated.View>
  </View>
 

旋转动画:

import React from 'react';
import  Animated, Text, View,
Button
 from 'react-native';

export default  class AnimatedViewScreen extends React.Component 
    degree=new Animated.Value(0)
    componentDidMount() 
     Animated.timing(this.degree,
            
                toValue:1,
                duration:3000,
             
            ).start();
    
    render() 
       const realDeg=this.degree.interpolate(
        inputRange:[0,1],
        outputRange:['0deg','360deg']
    );
        return (
            <View style=flex:1,justifyContent:'center',alignItems:'center'>
     <Animated.Image style=width:100,height:100,transform:[rotate:realDeg],
                 source=require('./image/tab_b_select.png')>
     </Animated.Image>
  </View>
 

这里我们使用了一个interpolate()插值函数,用于将输入值范围转换为输出值范围这里是将[0,1] 输入 转为[‘0deg’,‘360deg’];
interpolate变化过程也可以是多段的输入[0,0.5,1] ,输出为[‘0deg’,‘360deg’,‘0deg’]

缩放动画:

import React from 'react';
import  Animated, Text, View,
Button
 from 'react-native';

export default  class AnimatedViewScreen extends React.Component 
    scale=new Animated.Value(0)
    componentDidMount() 
    Animated.timing(this.scale,
            
                toValue:1,
                duration:3000,
            
        ).start();
    
    render() 
        return (
            <View style=flex:1,justifyContent:'center',alignItems:'center'>
    <Animated.View style=width:100,height:100,transform:[scale:this.scale]>
         <Button title='缩放按钮'/>
  </Animated.View>
  </View>
 

-组合动画

上面已经介绍了基本动画,透明度,平移,旋转,缩放,那么复杂的动画就需要这些基本变换的组合,也就是对这些基本动画的组合。

Animated API中提供了以下方法来实现组合动画:

Animated.parallel():参数是动画数组,同时开始动画数组中的全部动画。默认情况下有一个动画停止了,其余的也会停止,可以通过stopTogether选项设置false,来取消这种关联。

Animated.sequence():参数是动画数组,按照顺序执行动画中的所有数组,前一个动画执行完成后,后面一个动画再开始,如果当前动画被中止,则后面的动画不会继续执行;

Animated.stagger():参数是一个延迟时间和一个动画数组,前一个动画开始之后,一段时间后(延迟时间后),后一个动画开始;因为仅仅是前一个动画开始后指定时间,前一个动画并不一定结束了,所以会出现同时执行(重叠)的情况;

组合动画示例:

import React from 'react';
import  Animated, Text, View,
Button
 from 'react-native';

export default  class AnimatedViewScreen extends React.Component 
    sameTimeDegree=new Animated.Value(0)
    sameTimeScale=new Animated.Value(0)
    componentDidMount() 
    
    //释放出来看效果
    // Animated.parallel([
       //     this.createAnimation(this.sameTimeScale,3000),
       //     this.createAnimation(this.sameTimeDegree,3000)
       // ]).start()
       
         //释放出来看效果
        // Animated.sequence([
        //     this.createAnimation(this.sameTimeScale,3000),
        //     this.createAnimation(this.sameTimeDegree,3000)
        // ]).start()

        Animated.stagger(10000,[
            this.createAnimation(this.sameTimeScale,3000),
            this.createAnimation(this.sameTimeDegree,3000)
        ]).start()

    
    render() 
     const realSameTimeDeg=this.sameTimeDegree.interpolate(
        inputRange:[0,1],
        outputRange:['0deg','360deg']
    )
        return (
            <View style=flex:1,justifyContent:'center',alignItems:'center'>
 <Animated.Image
                 style=
                     width:100,
                     height:100,
                     transform:[
                         
                             scale:this.sameTimeScale
                         ,
                         rotate:realSameTimeDeg
                     ]
                 
                 source=require('./image/tab_b_select.png')
                >
                </Animated.Image>
  </View>
 

-一些注意点

(1)如何使动画循环执行

我们可能需要一个一直旋转的View;
Animated.start()方法可以传入一个参数,这个参数是一个函数,在动画结束时会回调这个函数,我们可以在这个函数里将属性值重新设置为初始值,然后再启动画以此来实现动画的循环执行;

循环动画示例:

import React from 'react';
import 
 Animated, 
 View,
 from 'react-native';
export default  class ProgressBar extends Component
      deg=new Animated.Value(0)
      rotate=Animated.timing(this.deg, 
             toValue: 1,        //属性目标值
             duration: 1000,    //动画执行时间
             easing: Easing.linear
    )
      componentDidMount() 
        this.startAnimate()
      
  
      startAnimate()
        this.deg.setValue(0)
        this.rotate.start(()=>this.startAnimate())
    

   render() 

       const realDeg=this.deg.interpolate(
            inputRange:[0,1],
            outputRange:['0deg','360deg']
        );
     return (
     
   <View style=flex:1,justifyContent:'center',alignItems:'center'>
      <Animated.Image style=width:100,height:100,transform:  [rotate:realDeg],
                 source=require('./image/tab_b_select.png')>
                
                </Animated.Image>
       <View/>    
    )
   

上面代码就是通过start()启动动画时传入函数,重新调用startAnimation()方法设置属性值为初始值,并重新启动动画实现动画循环执行,从而实现了一个一直旋转的图片这里要注意的是,Animated.timing()方法中easing:Easing.linear属性,也就是设置动画线性匀速播放,否则动画一次播放结束时,进入下一次动画时可能并不是连续的,会有停顿;

(2)创建动画组件

上面提到了除了Animated提供的支持的一些动画组件之外,我们可以使用Animated.createAnimatedComponent()方法来将任意组件变成动画组件;但是在实际尝试的过程中将Button变成动画组件好像无效,其他的组件都是有效的;

下面给出将TextInput变成动画组件,并进行动画的实例:

import React from 'react';
import 
    View,
    TextInput
 from 'react-native';
const AnimatedTextInput=Animated.createAnimatedComponent(TextInput);
export default class MainScreen extends React.Component
    scale=new Animated.Value(0);
     componentDidMount() 
        Animated.timing(  //随时间变化而执行动画
            this.scale,   //动画中的变量值
            
                toValue: 1,  //透明度最终变为1,即完全不透明
                duration: 3000,
            
        ).start();
   
   render()
     return (
            <View>
               <AnimatedTextInput style=width:100,height:200,
                    transform:[scale:this.scale],
                    backgroundColor:'red'
                 height=200>
                    请输入内容
                </AnimatedTextInput>
            </View>
      )
   

以上就是React Native 中Animated动画的基本使用

以上是关于React Native 动画(Animated)的主要内容,如果未能解决你的问题,请参考以下文章

使用 React Native Animated 时,可以为偏移设置动画吗?

React Native 动画(Animated)

React Native动画总结

react-native-Animated初探

react-native-Animated初探

如何在 React Native 中使用 Animated API 同时隐藏 Header 和 Footer