欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

React Native Animated 动画之 加载中loading

程序员文章站 2022-03-18 20:12:40
...

用RN的Animated做一个简单的加载中动画

加载中 是APP中很常见的一种交互,自己也是刚入手React Native,加载列表的时候需要一个loading状态,那我们就开始吧。

首先撸一遍思路

  1. 首先,在ReactNative中要使我们的loading图标允许动画,我们可以使用 createAnimatedComponent() 创建的组件加载我们的图标,或者直接使用Animated下默认封装好了的:
    Animated.Image
    Animated.ScrollView
    Animated.Text
    Animated.View
  2. 然后动画方式是我们熟悉的 属性:transform,写法和CSS3少许不同
  3. 接着是旋转动画rotate的值,通过Animated的方法不断更新

从文档开始

ReactNative-Animated文档
Animated的主要相关方法有4个:

Animated.decay()
Animated.spring()
Animated.timing()
Animated.loop()

前两个分别是特定曲线(衰弱、反弹)效果,这里我使用timing,便于自定义自己的动画效果。
timing函数接受2个参数,第一个初始value,第二个是配置json,类似:

Animated.timing(
    initValue, // 由new Animated.Value(0)创建
    {
        toValue: Number, // 动画到达值
        delay: Number, // 延迟动画,默认 0
        duration: Number, // initValue => toValue持续的时间,默认 500
        easing: Function, // 动画曲线
        useNativeDriver: Boolean, // 是否启用原生动画驱动,默认false
    }
  )

其中动画曲线函数可以参考 RN api-Easing
此时动画完成一半,只是从initValue转到toValue就结束了。要循环动画,这里有两种思路:

  1. Animated.timing(...).start(callback)动画执行完毕后的callback函数中再次调用此动画,类似

    let animation = Animated.timing(...);
    animation.start(animation.start)
  2. 使用Animated.loop()(本例)。关于loop方法:
    React Native Animated 动画之 加载中loading
    大概意思就是:
    其可接受2个参数:animation(可由上面3个方法创建);config(可选配置json:{iterations: Number, // 循环次数})。当useNativeDriver设置为true的时候,动画将不会阻塞页面UI、JS等线程。

还有一个注意点就是rotate的值是一个字符串,并且有单位,而我们的初始值和终点值以及期间的值都是 Number,所以这里会用到一个插值函数interpolate(),上面的文档以及这篇 RN-动画animations 里有提到。demo会用到。

贴上一个简单的demo

import React, { Component } from 'react';
import {
    View,
    Text,
    Image,
    Animated, // 这两个都是要引入的
    Easing,
} from 'react-native';

export default class Loading extends Component {
    state = {
        rotateVal: new Animated.Value(0), 
    }

    componentDidMount(){ // 组件加载完成后启动动画
        const animationLoading = Animated.timing(
            this.state.rotateVal, // 初始值
            {
                toValue: 360, // 终点值
                easing: Easing.linear, // 这里使用匀速曲线,详见RN-api-Easing
            }
        );
        Animated.loop(animationLoading).start(); // 开始动画
        setTimeout(Animated.loop(animationLoading).stop, 5000); // 5秒后停止动画,可用于任意时刻停止动画
    }

    render(){ // 渲染界面
        return(
            <View>
                // 我项目中用字体图标,所以这里用.Text,也可以用.Image加载一张图片,然后样式属性中transform
                <Animated.Text 
                    style={{
                        textAlign: 'center',
                        fontSize: 34,
                        fontFamily: 'iconfont',
                        transform: [{ // 动画属性
                            rotate: this.state.rotateVal.interpolate({
                                inputRange: [0, 360],
                                outputRange: ['0deg', '360deg'],
                            })
                        }]
                    }}>
                    {'\ue6ae'}
                </Animated.Text>
            </View>
        )
    }
}

当然还有许多组合操作,可以慢慢尝试