跳到主要内容

Animated

Animated 库旨在使动画流畅、强大且易于构建和维护。Animated 专注于输入和输出之间的声明式关系、中间的可配置转换,以及用于控制基于时间的动画执行的 startstop 方法。

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

不要直接修改动画值。你可以使用 useRef Hook 来返回一个可变的 ref 对象。该 ref 对象的 current 属性被初始化为给定的参数,并在组件的整个生命周期中持续存在。

示例

以下示例包含一个将根据动画值 fadeAnim 淡入淡出的 View

请参阅动画指南以查看更多实际应用中的 Animated 示例。

概述

有两种值类型可以与 Animated 一起使用:

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

配置动画

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

在大多数情况下,你将使用 timing()。默认情况下,它使用对称的 easeInOut 曲线,这种曲线表现了物体逐渐加速到全速,然后逐渐减速到停止的过程。

处理动画

通过在动画上调用 start() 来启动动画。start() 接受一个完成回调函数,该函数将在动画完成时被调用。如果动画正常运行结束,完成回调函数将接收到 {finished: true}。如果动画因在其完成前调用了 stop() 而结束(例如,被手势或其他动画打断),则将接收到 {finished: false}

tsx
Animated.timing({}).start(({finished}) => {
/* completion callback */
});

使用原生驱动

通过使用原生驱动,我们在启动动画之前将动画的所有信息发送到原生层,允许原生代码在 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):

tsx
 onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{nativeEvent: {
contentOffset: {
x: scrollX
}
}
}]
)}

参考

方法

当给定值是 ValueXY 而不是 Value 时,每个配置选项可能是一个 {x: ..., y: ...} 形式的矢量,而不是标量。

decay()

tsx
static decay(value, config): CompositeAnimation;

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

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

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

timing()

tsx
static timing(value, config): CompositeAnimation;

沿定时缓动曲线动画一个值。Easing 模块有大量的预定义曲线,你也可以使用自己的函数。

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

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

spring()

tsx
static spring(value, config): CompositeAnimation;

根据基于阻尼谐振的解析弹簧模型动画一个值。跟踪速度状态,以便在 toValue 更新时创建流畅的运动,并且可以串联。

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

请注意,你只能定义 bounciness/speed、tension/friction 或 stiffness/damping/mass 中的一个,不能定义多个。

friction/tension 或 bounciness/speed 选项与 Facebook PopReboundOrigami 中的弹簧模型匹配。

  • 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:此动画是否在 InteractionManager 上创建一个“交互句柄”。默认为 true。
  • useNativeDriver:为 true 时使用原生驱动。必需。

add()

tsx
static add(a: Animated, b: Animated): AnimatedAddition;

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


subtract()

tsx
static subtract(a: Animated, b: Animated): AnimatedSubtraction;

创建一个由第一个 Animated 值减去第二个 Animated 值组成的新 Animated 值。


divide()

tsx
static divide(a: Animated, b: Animated): AnimatedDivision;

创建一个由第一个 Animated 值除以第二个 Animated 值组成的新 Animated 值。


multiply()

tsx
static multiply(a: Animated, b: Animated): AnimatedMultiplication;

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


modulo()

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

创建一个由提供的 Animated 值(非负)取模得到的新 Animated 值。


diffClamp()

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

创建一个限制在两个值之间的新 Animated 值。它使用当前值与上一个值之间的差值,因此即使值远离边界,当值再次接近边界时也会开始变化。(即 值 = clamp(值 + 差值, 最小值, 最大值))。

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


delay()

tsx
static delay(time: number): CompositeAnimation;

在给定延迟后开始动画。


sequence()

tsx
static sequence(animations: CompositeAnimation[]): CompositeAnimation;

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


parallel()

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

同时开始一个动画数组。默认情况下,如果其中一个动画停止,所有动画都会停止。你可以使用 stopTogether 标志来覆盖此行为。


stagger()

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

动画数组可以并行运行(重叠),但会按顺序并带有逐个增加的延迟启动。适用于制作尾随效果。


loop()

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

连续循环给定的动画,使得每次到达结束时都会重置并从头开始。如果子动画设置为 useNativeDriver: true,则循环不会阻塞 JS 线程。此外,循环可能会阻止基于 VirtualizedList 的组件在动画运行时渲染更多行。你可以在子动画配置中传递 isInteraction: false 来解决此问题。

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

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

event()

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

接受一个映射数组,并相应地从每个参数中提取值,然后对映射的输出调用 setValue。例如:

tsx
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: this._scrollX}}}],
{listener: (event: ScrollEvent) => console.log(event)}, // Optional async listener
)}
...
onPanResponderMove: Animated.event(
[
null, // raw event arg ignored
{dx: this._panX},
], // gestureState arg
{
listener: (
event: GestureResponderEvent,
gestureState: PanResponderGestureState
) => console.log(event, gestureState),
} // Optional async listener
);

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

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

forkEvent()

jsx
static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;

用于监视通过 props 传入的动画事件的高级命令式 API。它允许向现有 AnimatedEvent 添加新的 javascript 监听器。如果 animatedEvent 是 javascript 监听器,它将把两个监听器合并为一个;如果 animatedEvent 为 null/undefined,它将直接分配 javascript 监听器。在可能的情况下直接使用值。


unforkEvent()

jsx
static unforkEvent(event: AnimatedEvent, listener: Function);

start()

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

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

参数

名称类型是否必需描述
callback(result: {finished: boolean}) => void动画正常运行结束后,或动画因在其完成前调用了 stop() 而结束时调用的函数。

带有回调函数的 Start 示例

tsx
Animated.timing({}).start(({finished}) => {
/* completion callback */
});

stop()

tsx
static stop();

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


reset()

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: trueAnimated.event