跳到主要内容

Animated

Animated 库旨在使动画流畅、强大且易于构建和维护。Animated 侧重于输入和输出之间的声明性关系、两者之间可配置的转换以及用于控制基于时间的动画执行的 start/stop 方法。

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

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

示例

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

请参阅动画指南,以查看 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() 直接映射到动画值。这是通过结构化映射语法完成的,以便可以从复杂的事件对象中提取值。第一层是一个数组,允许跨多个 args 进行映射,并且该数组包含嵌套对象。

例如,当处理水平滚动手势时,您将执行以下操作,以便将 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/tensionbounciness/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 值,该值限制在 2 个值之间。它使用最后一个值之间的差值,因此即使该值远离边界,当该值开始再次靠近时,它也会开始更改。(value = clamp(value + diff, min, max))。

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


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;

接受映射数组并相应地从每个 arg 中提取值,然后在映射的输出上调用 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 侦听器,它会将 2 个侦听器合并为一个,如果 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() 而完成时将调用的函数

带有回调的启动示例

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

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

您可以在单独的页面上阅读有关 Animated.ValueXY API 的更多信息。


Interpolation

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


Node

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


createAnimatedComponent

使任何 React 组件都可动画化。用于创建 Animated.View 等。


attachNativeEvent

用于将动画值附加到视图上事件的命令式 API。如果可能,首选使用带有 useNativeDriver: trueAnimated.event