[TOC]

概述

流畅、有意义的动画对于移动应用用户体验来说是非常重要的。现实生活中的物体在开始移动和停下来的时候都具有一定的惯性,我们在界面中也可以使用动画来实现契合物理规律的交互。

React Native 提供了两个互补的动画系统:用于创建精细的交互控制的动画Animated和用于全局的布局动画LayoutAnimation。

Animated

Animated使得开发者可以简洁地实现各种各样的动画和交互方式,并且具备极高的性能。Animated旨在以声明的形式来定义动画的输入与输出,在其中建立一个可配置的变化函数,然后使用start/stop方法来控制动画按顺序执行。 Animated仅封装了6个可以动画化的组件:View、Text、Image、ScrollView、FlatList和SectionList,不过你也可以使用Animated.createAnimatedComponent()来封装你自己的组件。下面是一个在加载时带有淡入动画效果的视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import React, { useState, useEffect } from 'react';
import { Animated, Text, View } from 'react-native';

const FadeInView = (props) => {
const [fadeAnim] = useState(new Animated.Value(0)) // 透明度初始值设为0

React.useEffect(() => {
Animated.timing( // 随时间变化而执行动画
fadeAnim, // 动画中的变量值
{
toValue: 1, // 透明度最终变为1,即完全不透明
duration: 10000, // 让动画持续一段时间
}
).start(); // 开始执行动画
}, [])

return (
<Animated.View // 使用专门的可动画化的View组件
style={{
...props.style,
opacity: fadeAnim, // 将透明度绑定到动画变量值
}}
>
{props.children}
</Animated.View>
);
}

<!--然后你就可以在组件中像使用`View`那样去使用`FadeInView`了-->
export default () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FadeInView style={{width: 250, height: 50, backgroundColor: 'powderblue'}}>
<Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
</FadeInView>
</View>
)
}

我们来分解一下这个过程。在FadeInView的构造函数里,我们创建了一个名为fadeAnim的Animated.Value,并放在state中。而View的透明度是和这个值绑定的。

组件加载时,透明度首先设为 0。然后一个easing动画开始改变fadeAnim值,同时会导致所有与其相关联的值(本例中是透明度)也逐帧更新,最终和fadeAnim一样变为1。

这一过程经过特别优化,执行效率会远高于反复调用setState和多次重渲染。

因为这一过程是纯声明式的,因此还有进一步优化的空间,比如我们可以把这些声明的配置序列化后发送到一个高优先级的线程上运行。

配置动画

动画拥有非常灵活的配置项。自定义的或预定义的 easing 函数、延迟、持续时间、衰减系数、弹性常数等都可以在对应类型的动画中进行配置。

Animated提供了多种动画类型,其中最常用的要属Animated.timing().

它支持使用各种预定义的缓动函数之一随时间动画一个值,或者您也可以使用自己的缓动函数。缓动函数通常用在动画中来表示物体的逐渐加速和减速。

默认情况下,计时将使用一个easeInOut曲线,它将逐渐加速到全速,并通过逐渐减速到停止来结束。

您可以通过传递一个缓动参数来指定一个不同的缓动函数。还支持自定义持续时间,甚至是动画开始前的延迟。

下面这个例子创建了一个2秒长的动画,在移动目标到最终位置前会稍微往后退一点:

1
2
3
4
5
Animated.timing(this.state.xPosition, {
toValue: 100,
easing: Easing.back(),
duration: 2000
}).start();

组合动画

多个动画可以通过parallel(同时执行)、sequence(顺序执行)、stagger和delay来组合使用。它们中的每一个都接受一个要执行的动画数组,并且自动在适当的时候调用start/stop。

例如,下面的动画滑行到停止,然后在平行旋转时弹回:

文章参考:https://juejin.im/entry/583ab7e2ac502e006ea34edd