跳到主要内容
版本:Next

动画

Animated 库旨在让动画的构建和维护变得流畅、强大且轻松。Animated 专注于输入与输出之间的声明式关系,以及中间可配置的转换,并通过 start/stop 方法来控制基于时间的动画执行。

创建动画的核心流程是先创建一个 Animated.Value,将其绑定到动画组件的一个或多个样式属性上,然后使用 Animated.timing() 通过动画来驱动更新。

备注

不要直接修改 animated value。你可以使用 useRef 钩子 返回一个可变的 ref 对象。该 ref 对象的 current 属性会以给定参数初始化,并在组件生命周期内持续存在。

示例​

下面的示例包含一个 View,它会根据动画值 fadeAnim 实现淡入和淡出

参阅 动画 指南,查看更多 Animated 的使用示例。

概览​

你可以将以下两种值类型与 Animated 一起使用:

Animated.Value 可以绑定到样式属性或其他属性,也可以进行插值。一个 Animated.Value 可以驱动任意数量的属性。

配置动画​

Animated 提供三种动画类型。每种动画类型都提供一种特定的动画曲线,用于控制值如何从初始值过渡到最终值:

在大多数情况下,你会使用 timing()。默认情况下,它使用对称的 easeInOut 曲线,表现为对象逐渐加速到最高速度,并在结束时逐渐减速直至停止。

使用动画​

通过在动画上调用 start() 来启动动画。start() 接受一个完成回调,该回调会在动画结束时被调用。如果动画正常结束,完成回调会收到 {finished: true}。如果动画因为在完成前被调用 stop() 而结束(例如被手势或另一个动画中断),则会收到 {finished: false}。

React TSX
Animated.timing({}).start(({finished}) => {
/* 完成回调 */
});

使用原生驱动​

使用原生驱动时,我们会在动画开始前把关于动画的所有内容发送到原生端,这样原生代码就可以在 UI 线程上执行动画,而无需在每一帧都经过桥接层。一旦动画开始,JS 线程即使被阻塞也不会影响动画。

你可以在动画配置中指定 useNativeDriver: true 来使用原生驱动。更多信息请参阅动画指南。

可动画组件​

只有可动画组件才能被动画化。这些特殊组件负责将动画值绑定到属性上,并进行有针对性的原生更新,以避免每一帧都付出 React 渲染和协调过程的成本。它们还会在卸载时处理清理,因此默认是安全的。

Animated 使用上面的包装器导出以下可动画组件:

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

组合动画​

还可以使用组合函数以更复杂的方式组合动画:

也可以通过将一个动画的 toValue 设置为另一个 Animated.Value 来将动画链式连接。请参阅动画指南中的跟踪动态值。

默认情况下,如果一个动画停止或被中断,组中的所有其他动画也会停止。

组合动画值​

你可以通过加法、减法、乘法、除法或取模将两个动画值组合成一个新的动画值:

插值​

interpolate() 函数允许将输入区间映射到不同的输出区间。默认情况下,它会将曲线在给定区间之外进行外推,但你也可以让它将输出值限制在边界内。它默认使用线性插值,但也支持缓动函数。

更多关于插值的内容,请参阅动画指南。

处理手势和其他事件​

手势,例如拖动或滚动,以及其他事件,都可以通过 Animated.event() 直接映射到动画值。这通过结构化的映射语法完成,以便从复杂的事件对象中提取值。第一层是一个数组,用于支持跨多个参数的映射,而该数组中包含嵌套对象。

例如,在处理水平滚动手势时,你会按如下方式将 event.nativeEvent.contentOffset.x 映射到 scrollX(一个 Animated.Value):

React TSX
onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{nativeEvent: {
contentOffset: {
x: scrollX
}
}
}],
{useNativeEvent: true}
)}

参考

方法​

当给定值是 ValueXY 而不是 Value 时,每个配置项都可以是形如 {x: ..., y: ...} 的向量,而不是标量。

decay()​

React TSX
static decay(value, config): CompositeAnimation;

根据衰减系数,将一个值从初始速度动画到 0。

配置是一个对象,可能包含以下选项:

  • velocity: 初始速度。必需。
  • deceleration: 衰减率。默认 0.997。
  • isInteraction: 此动画是否创建“交互句柄”。默认 true。
  • useNativeDriver: 为 true 时使用原生驱动。必需。

timing()​

React TSX
static timing(value, config): CompositeAnimation;

沿着一个定时的缓动曲线为值添加动画。Easing 模块提供了大量预定义曲线,你也可以使用自己的函数。

配置是一个对象,可能包含以下选项:

  • duration: 动画时长(毫秒)。默认 500。
  • easing: 用于定义曲线的缓动函数。默认为 Easing.inOut(Easing.ease)。
  • delay: 延迟后启动动画(毫秒)。默认 0。
  • isInteraction: 此动画是否创建“交互句柄”。默认 true。
  • useNativeDriver: 为 true 时使用原生驱动。必需。

spring()​

React TSX
static spring(value, config): CompositeAnimation;

根据基于 阻尼谐振荡 的解析弹簧模型为值添加动画。它会跟踪速度状态,以便在 toValue 更新时创建流畅运动,并且可以链式连接。

配置是一个对象,可能包含以下选项。

请注意,你只能定义 bounciness/speed、tension/friction 或 stiffness/damping/mass 中的一组,而不能同时定义多组:

friction/tension 或 bounciness/speed 选项与 Facebook Pop、Rebound 和 Origami 中的弹簧模型相匹配。

  • friction:控制“弹性”/超调。默认 7。
  • tension:控制速度。默认 40。
  • speed:控制动画速度。默认 12。
  • bounciness:控制弹性。默认 8。

将 stiffness/damping/mass 作为参数指定后,Animated.spring 会使用基于 阻尼谐振子 运动方程的解析弹簧模型。这个行为稍微更精确,也更贴近弹簧动力学背后的物理原理,并且与 iOS 中的 CASpringAnimation 实现非常接近。

  • stiffness:弹簧刚度系数。默认 100。
  • damping:定义由于摩擦力导致弹簧运动应如何衰减。默认 10。
  • mass:连接在弹簧末端的物体质量。默认 1。

其他配置选项如下:

  • velocity: 连接到弹簧的物体的初始速度。默认 0(物体处于静止状态)。
  • overshootClamping: 一个布尔值,表示是否应限制弹簧使其不发生反弹。默认 false。
  • restDisplacementThreshold: 位移低于此阈值时,弹簧将被视为处于静止状态。默认 0.001。
  • restSpeedThreshold: 速度低于此值时,弹簧将被视为处于静止状态,单位为每秒像素。默认 0.001。
  • delay: 延迟后启动动画(毫秒)。默认 0。
  • isInteraction: 此动画是否创建“交互句柄”。默认 true。
  • useNativeDriver: 为 true 时使用原生驱动。必需。

add()​

React TSX
static add(a: Animated, b: Animated): AnimatedAddition;

创建一个新的 Animated 值,由两个相加的 Animated 值组成。


subtract()​

React TSX
static subtract(a: Animated, b: Animated): AnimatedSubtraction;

创建一个新的 Animated 值,通过从第一个 Animated 值中减去第二个 Animated 值组成。


divide()​

React TSX
static divide(a: Animated, b: Animated): AnimatedDivision;

创建一个新的 Animated 值,通过将第一个 Animated 值除以第二个 Animated 值组成。


multiply()​

React TSX
static multiply(a: Animated, b: Animated): AnimatedMultiplication;

创建一个新的 Animated 值,由两个相乘的 Animated 值组成。


modulo()​

React TSX
static modulo(a: Animated, modulus: number): AnimatedModulo;

创建一个新的 Animated 值,它是所提供 Animated 值的(非负)取模结果


diffClamp()​

React TSX
static diffClamp(a: Animated, min: number, max: number): AnimatedDiffClamp;

创建一个新的 Animated 值,将其限制在两个值之间。它使用上一个值的差值,因此即使该值远离边界,只要它开始再次接近边界,就会开始变化。(value = clamp(value + diff, min, max))。

这在滚动事件中非常有用,例如,向上滚动时显示导航栏,向下滚动时将其隐藏。


delay()​

React TSX
static delay(time: number): CompositeAnimation;

在给定延迟后启动动画。


sequence()​

React TSX
static sequence(animations: CompositeAnimation[]): CompositeAnimation;

按顺序启动一组动画,在开始下一个之前等待每个动画完成。如果当前正在运行的动画被停止,则不会启动后续动画。


parallel()​

React TSX
static parallel(
animations: CompositeAnimation[],
config?: ParallelConfig
): CompositeAnimation;

同时启动一组动画。默认情况下,如果其中一个动画停止,则它们全部都会停止。你可以使用 stopTogether 标志覆盖这一行为。


stagger()​

React TSX
static stagger(
time: number,
animations: CompositeAnimation[]
): CompositeAnimation;

一组动画可以并行运行(重叠),但会按顺序并以连续延迟启动。适合用于创建拖尾效果。


loop()​

React TSX
static loop(
animation: CompositeAnimation[],
config?: LoopAnimationConfig
): CompositeAnimation;

持续循环给定动画,使其每次到达末尾时重置并从头开始重新执行。如果子动画设置为 useNativeDriver: true,则循环不会阻塞 JS 线程。此外,循环可能会阻止基于 VirtualizedList 的组件在动画运行时渲染更多行。你可以在子动画配置中传入 isInteraction: false 来修复这一点。

配置是一个对象,可能包含以下选项:

  • iterations:动画应循环的次数。默认 -1(无限)。

event()​

React TSX
static event(
argMapping: Mapping[],
config?: EventConfig
): (...args: any[]) => void;

接收一个映射数组,并按相应方式从每个参数中提取值,然后在映射后的输出上调用 setValue。例如:

React TSX
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: this._scrollX}}}],
{listener: (event: ScrollEvent) => console.log(event)}, // 可选的异步监听器
)}
...
onPanResponderMove: Animated.event(
[
null, // 原始事件参数会被忽略
{dx: this._panX},
], // gestureState 参数
{
listener: (
event: GestureResponderEvent,
gestureState: PanResponderGestureState
) => console.log(event, gestureState),
} // 可选的异步监听器
);

配置是一个对象,可能包含以下选项:

  • listener:可选的异步监听器。
  • useNativeDriver:为 true 时使用原生驱动。必需。

forkEvent()​

React JSX
static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;

用于窥探通过 props 传入的 animated 事件的高级命令式 API。它允许向现有的 AnimatedEvent 添加一个新的 JavaScript 监听器。如果 animatedEvent 是一个 JavaScript 监听器,它会将这两个监听器合并为一个;如果 animatedEvent 为 null/undefined,则会直接分配 JavaScript 监听器。尽可能直接使用值。


unforkEvent()​

React JSX
static unforkEvent(event: AnimatedEvent, listener: Function);

start()​

React TSX
static start(callback?: (result: {finished: boolean}) => void);

通过在动画上调用 start() 来启动动画。start() 接受一个完成回调,该回调会在动画结束时或在动画因为在完成前被调用 stop() 而结束时被调用。

参数:

名称类型是否必需说明
callback(result: {finished: boolean}) => void否函数,会在动画正常结束后,或在动画因为在完成前被调用 stop() 而结束后被调用

带回调的启动示例:

React TSX
Animated.timing({}).start(({finished}) => {
/* 完成回调 */
});

stop()​

React TSX
static stop();

停止任何正在运行的动画。


reset()​

React TSX
static reset();

停止任何正在运行的动画,并将值重置为其初始值。

属性​

Value​

用于驱动动画的标准值类。通常在函数组件中使用 useAnimatedValue(0); 初始化,或在类组件中使用 new Animated.Value(0); 初始化。

你可以在单独的 页面 上了解更多关于 Animated.Value API 的内容。


ValueXY​

用于驱动二维动画的二维值类,例如平移手势。

你可以在单独的 页面 上了解更多关于 Animated.ValueXY API 的内容。


Interpolation​

导出该项以在 flow 中使用 Interpolation 类型。


Node​

为方便类型检查而导出。所有动画值都派生自此类。


createAnimatedComponent​

将任意 React 组件变为可动画化组件。用于创建 Animated.View 等。


attachNativeEvent​

用于将动画值以命令式 API 绑定到视图上的事件。若可能,优先使用带有 useNativeDriver: true 的 Animated.event。