React Native 动画组件 Animated

动作 给予一个物体生命。比如一个石头,是不会动的,除非外力,不然它永远在那里。

而有生命的物体,会有各种动作,可以从一个地方走到另一个地方,可以模仿其它动物,会吃,会喝,会睡觉。

App 也一样。如果只是简单的展示,浏览它的人就会觉得枯燥无味。但一定用户的点击有了响应,那就会觉得特别亲切。

动画是在动作的基础上更上一层,它对开始到结束的动作结果赋予了变化的过程。让使用者可以从视觉感知的看到动作的变化。

Android 和 iOS 原生自带了超级多的动画,比如 Android 动画 就可以分为三大类:逐帧动画(Frame)补间动画(Tween)属性动画 (Property)

而 iOS 也毫不逊色,通过 Core Animation 提供了 基础动画(CABasicAnimation)关键帧动画(CAKeyframeAnimation)组动画(CAAnimationGroup)过渡动画(CATransition)

React Native 是一个跨平台的开发环境。既然要跨平台,那就必须通过一种通用的方式把 iOS 和 Android 的动画包装起来。这个包装的结果就是 动画组件 Animated

React Native 动画组件 Animated

React Native 动画组件 Animated 是对 Android 和 iOS 动画的封装,以统一的接口的提供了为 React Native 提供了动画功能。

动画组件 Animated 提供的是一种值动画,也就是属性改变动画。也就是通过动态的不断的改变控件的某个属性的值来达到动画的目的。

当我们需要创建一个动画时,我们必须先初始化一个值。React Native Animated 组件提供了两种值类型

值类型 说明
Animated.Value() 单个值变化
Animated.ValueXY() 两个值变化

Animated 组件提供了三种类型来控制动画的缓动过程。

函数 说明
Animated.decay() 以摩擦力模型来控制动画的缓动,简单的说就是以初始速度开始并逐渐减速到停止
Animated.spring() 使用弹簧物理模型来控制动画的缓动
Animated.timing() 使用时间来控制动画的缓动

默认情况下, React Native 只能对以下组件提供动画功能

Animated.Image
Animated.ScrollView
Animated.Text
Animated.View
Animated.FlatList
Animated.SectionList

如果其它组件也需要动画动能,那么需要使用 createAnimatedComponent() 函数来开启动画功能。

总之,React Native 动画组件 Animated 有点复杂,详细功能可以直接参考文档。

React Native 动画组件 Animated 的创建过程

  1. 首先,一般给要创建动画的组件设置一个初始的样式,这个通过 style 属性来解决。

    例如下面的代码为某个 box 组件设置了初始化的 背景色

    const styles = StyleSheet.create({
    
        box: {
            backgroundColor: 'blue',
            width: 50,
            height: 100
        }
    })
    
  2. 其次,在组件即将加载的生命周期函数 componentWillMount() 中初始化动画。

    componentWillMount = () => {
        this.animatedWidth = new Animated.Value(50)
        this.animatedHeight = new Animated.Value(100)
    }
    

    初始化动画使用 Animated.Value()Animated.ValueXY() 来实现。

    例如

    new Animated.Value(50)
    

    这是什么意思呢? 比如我们要实现动画:长从 50 变化到 100。 那么动画初始化的时候就需要把值 50 传递给 Animated.Value(50)

  3. 使用动画类型来定义动画滑动的过程。这个一般包装在某个函数里面

    animatedBox = () => {
        Animated.timing(this.animatedWidth, {
            toValue: 200,
            duration: 1000
        }).start()
        Animated.timing(this.animatedHeight, {
            toValue: 500,
            duration: 500
        }).start()
    }
    

    Animated.timing() 用于定义随时间变化的函数。它的函数原型如下

    static timing(value, config)
    

    各个参数说明如下

    参数 说明
    value 要实现缓动的值。也就是我们第一步中初始化的动画
    config 配置动画缓动的各种参数

    config 可配置的参数如下

    参数 说明
    toValue 用于设置动画结束的值
    duration 动画时长,单位为 毫秒,默认值是 500
    easing 时间缓动曲线函数。默认值为渐入渐出 Easing.inOut 别名 Easing.ease
    delay 延迟多少毫秒才开始动画,默认值是 0
    isInteraction 此动画是否在 InteractionManager 上创建 "交互句柄"。默认为 true
    useNativeDriver 是否使用原生动画来实现,默认值是 false

    .start() 方法用于开始一个动画。

  4. 将初始化的动画和属性包装成一个样式。我们后面会用这个样式去覆盖动画组件的默认样式。

    const animatedStyle = { width: this.animatedWidth, height: this.animatedHeight }
    
  5. 重点来了,接下来我们要使用 <Animated.xxx> 组件定一个自定义动画组件。然后把这个自定义动画组件包裹在想要设置动画的组件里。

    <TouchableOpacity style = {styles.container} onPress = {this.animatedBox}>
        <Animated.View style = {[styles.box, animatedStyle]}/>
    </TouchableOpacity>
    

    <TouchableOpacity> 是我们想要实现的动画的组件。onPress = {this.animatedBox} 设置表示当点击的时候才开始动画。

    <Animated.View> 是系统内置的可添加动画的组件。它的实际意思就是说这个动画其实是一个针对 <View> 组件属性的动画。它的 style 属性有两个值。

    style = {[styles.box, animatedStyle]}
    

    这两个值是合并的意思,就是 animatedStyle 里设置的样式会覆盖 styles.box 设置的样式。

范例

下面的代码,我们使用 Animated 动画组件动态改变 <TouchableOpacity> 视图的

相关代码逻辑我们前面已经讲述了,我们就不再详细展开,直接上代码.

App.js

import React, { Component } from 'react'
import { View, StyleSheet, Animated, TouchableOpacity } from 'react-native'

class App extends Component {
   componentWillMount = () => {
      this.animatedWidth = new Animated.Value(50)
      this.animatedHeight = new Animated.Value(100)
   }
   animatedBox = () => {
      Animated.timing(this.animatedWidth, {
         toValue: 200,
         duration: 1000
      }).start()
      Animated.timing(this.animatedHeight, {
         toValue: 500,
         duration: 500
      }).start()
   }
   render() {
      const animatedStyle = {
            width: this.animatedWidth, 
            height: this.animatedHeight }
      return (
         <TouchableOpacity 
            style = {styles.container} 
            onPress = {this.animatedBox}>
            <Animated.View style = {[styles.box, animatedStyle]}/>
         </TouchableOpacity>
      )
   }
}
export default App

const styles = StyleSheet.create({
   container: {
      justifyContent: 'center',
      alignItems: 'center'
   },
   box: {
      backgroundColor: 'blue',
      width: 50,
      height: 100
   }
})

运行效果如下

当我们第一次点击的时候就会出现动画,当第二次点击的时候就不会出现了,因为这时候 TouchableOpacity 的长宽已经和动画结束时的值时一样的了。

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.