Animated
Animated
库旨在使动画流畅、强大、易于构建和维护。Animated
专注于输入和输出之间的声明性关系、其间可配置的转换,以及控制基于时间的动画执行的 start
/stop
方法。
创建动画的核心工作流程是创建一个 Animated.Value
,将其连接到一个或多个动画组件的样式属性,然后使用 Animated.timing()
通过动画驱动更新。
不要直接修改动画值。您可以使用 useRef
Hook 返回一个可变的引用对象。此引用对象的 current
属性初始化为给定参数,并在整个组件生命周期中保持不变。
示例
以下示例包含一个 View
,它将根据动画值 fadeAnim
淡入淡出
请参阅动画指南,查看更多 Animated
的实际应用示例。
概述
您可以通过 Animated
使用两种值类型
Animated.Value()
用于单个值Animated.ValueXY()
用于向量
Animated.Value
可以绑定到样式属性或其他属性,也可以进行插值。单个 Animated.Value
可以驱动任意数量的属性。
配置动画
Animated
提供三种类型的动画。每种动画类型都提供一个特定的动画曲线,控制您的值如何从初始值动画到最终值
Animated.decay()
以初始速度开始,并逐渐减速停止。Animated.spring()
提供一个基本的弹簧物理模型。Animated.timing()
使用缓动函数随时间动画值。
在大多数情况下,您将使用 timing()
。默认情况下,它使用对称的 easeInOut 曲线,传达对象逐渐加速到全速,并以逐渐减速停止结束。
使用动画
通过在动画上调用 start()
来启动动画。start()
接受一个完成回调,该回调将在动画完成时调用。如果动画正常运行完成,完成回调将以 {finished: true}
调用。如果动画在完成之前因调用 stop()
而结束(例如,因为它被手势或另一个动画中断),那么它将接收 {finished: false}
。
Animated.timing({}).start(({finished}) => {
/* completion callback */
});
使用原生驱动
通过使用原生驱动,我们在开始动画之前将所有关于动画的信息发送到原生层,允许原生代码在 UI 线程上执行动画,而无需在每一帧都通过桥接。一旦动画开始,JS 线程可以被阻塞而不会影响动画。
您可以通过在动画配置中指定 useNativeDriver: true
来使用原生驱动。请参阅动画指南了解更多信息。
可动画组件
只有可动画组件才能进行动画。这些独特的组件通过将动画值绑定到属性,并执行有针对性的原生更新来避免 React 渲染和每一帧的协调过程的开销。它们还处理卸载时的清理,因此默认情况下是安全的。
createAnimatedComponent()
可用于使组件可动画化。
Animated
使用上述包装器导出以下可动画组件
Animated.Image
Animated.ScrollView
Animated.Text
Animated.View
Animated.FlatList
Animated.SectionList
组合动画
动画也可以使用组合函数以复杂的方式组合
Animated.delay()
在给定延迟后启动动画。Animated.parallel()
同时启动多个动画。Animated.sequence()
按顺序启动动画,等待每个动画完成后再启动下一个。Animated.stagger()
按顺序并行启动动画,但具有连续的延迟。
动画还可以通过将一个动画的 toValue
设置为另一个 Animated.Value
来链接在一起。请参阅动画指南中的跟踪动态值。
默认情况下,如果一个动画停止或中断,则组中的所有其他动画也会停止。
组合动画值
您可以通过加法、减法、乘法、除法或模运算组合两个动画值,以生成一个新的动画值
插值
interpolate()
函数允许输入范围映射到不同的输出范围。默认情况下,它将超出给定范围外推曲线,但您也可以使其限制输出值。它默认使用线性插值,但也支持缓动函数。
在动画指南中阅读更多关于插值的信息。
处理手势和其他事件
手势,如平移或滚动,以及其他事件可以使用 Animated.event()
直接映射到动画值。这通过结构化的映射语法完成,以便可以从复杂的事件对象中提取值。第一层是一个数组,允许跨多个参数进行映射,并且该数组包含嵌套对象。
例如,当处理水平滚动手势时,您将执行以下操作以将 event.nativeEvent.contentOffset.x
映射到 scrollX
(一个 Animated.Value
)
onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{nativeEvent: {
contentOffset: {
x: scrollX
}
}
}]
)}
参考
方法
当给定值为 ValueXY 而不是 Value 时,每个配置选项可以是 {x: ..., y: ...}
形式的向量,而不是标量。
decay()
static decay(value, config): CompositeAnimation;
根据衰减系数将值从初始速度动画到零。
Config 是一个对象,可以包含以下选项
velocity
:初始速度。必需。deceleration
:衰减率。默认 0.997。isInteraction
:此动画是否在InteractionManager
上创建“交互句柄”。默认 true。useNativeDriver
:当为 true 时使用原生驱动。必需。
timing()
static timing(value, config): CompositeAnimation;
沿定时缓动曲线动画值。 Easing
模块包含大量预定义曲线,您也可以使用自己的函数。
Config 是一个对象,可以包含以下选项
duration
:动画时长(毫秒)。默认 500。easing
:定义曲线的缓动函数。默认是Easing.inOut(Easing.ease)
。delay
:延迟(毫秒)后开始动画。默认 0。isInteraction
:此动画是否在InteractionManager
上创建“交互句柄”。默认 true。useNativeDriver
:当为 true 时使用原生驱动。必需。
spring()
static spring(value, config): CompositeAnimation;
根据基于阻尼谐振子的解析弹簧模型动画值。跟踪速度状态以在 toValue
更新时创建流畅的运动,并且可以链接在一起。
Config 是一个对象,可以包含以下选项。
请注意,您只能定义bounciness/speed、tension/friction或stiffness/damping/mass之一,不能定义多个
摩擦/张力或弹性/速度选项与 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
:此动画是否在InteractionManager
上创建“交互句柄”。默认 true。useNativeDriver
:当为 true 时使用原生驱动。必需。
add()
static add(a: Animated, b: Animated): AnimatedAddition;
创建一个由两个相加的 Animated 值组成的新 Animated 值。
subtract()
static subtract(a: Animated, b: Animated): AnimatedSubtraction;
创建一个由第一个 Animated 值减去第二个 Animated 值组成的新 Animated 值。
divide()
static divide(a: Animated, b: Animated): AnimatedDivision;
创建一个由第一个 Animated 值除以第二个 Animated 值组成的新 Animated 值。
multiply()
static multiply(a: Animated, b: Animated): AnimatedMultiplication;
创建一个由两个相乘的 Animated 值组成的新 Animated 值。
modulo()
static modulo(a: Animated, modulus: number): AnimatedModulo;
创建一个新的 Animated 值,该值是提供的 Animated 值的(非负)模
diffClamp()
static diffClamp(a: Animated, min: number, max: number): AnimatedDiffClamp;
创建一个新的 Animated 值,该值限制在两个值之间。它使用上次值之间的差异,因此即使该值远离边界,当该值再次接近时,它也会开始变化。(value = clamp(value + diff, min, max)
)。
这对于滚动事件很有用,例如,在向上滚动时显示导航栏,在向下滚动时隐藏导航栏。
delay()
static delay(time: number): CompositeAnimation;
在给定延迟后开始动画。
sequence()
static sequence(animations: CompositeAnimation[]): CompositeAnimation;
按顺序启动一组动画,等待每个动画完成后再启动下一个。如果当前正在运行的动画停止,则后续动画将不会启动。
parallel()
static parallel(
animations: CompositeAnimation[],
config?: ParallelConfig
): CompositeAnimation;
同时启动一组动画。默认情况下,如果其中一个动画停止,它们都会停止。您可以使用 stopTogether
标志覆盖此行为。
stagger()
static stagger(
time: number,
animations: CompositeAnimation[]
): CompositeAnimation;
动画数组可以并行(重叠)运行,但会按顺序启动,并带有连续延迟。非常适合实现拖尾效果。
loop()
static loop(
animation: CompositeAnimation[],
config?: LoopAnimationConfig
): CompositeAnimation;
持续循环给定动画,使其每次到达末尾时都会重置并从头开始。如果子动画设置为 useNativeDriver: true
,则循环不会阻塞 JS 线程。此外,循环可能会阻止基于 VirtualizedList
的组件在动画运行时渲染更多行。您可以在子动画配置中传递 isInteraction: false
来解决此问题。
Config 是一个对象,可以包含以下选项
iterations
:动画应循环的次数。默认-1
(无限)。
event()
static event(
argMapping: Mapping[],
config?: EventConfig
): (...args: any[]) => void;
接受一个映射数组,并根据每个参数提取值,然后对映射的输出调用 setValue
。例如:
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()
static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;
高级命令式 API,用于窥探通过 props 传入的动画事件。它允许向现有的 AnimatedEvent
添加新的 javascript 监听器。如果 animatedEvent
是一个 javascript 监听器,它将合并这两个监听器为一个;如果 animatedEvent
为 null/undefined,它将直接分配 javascript 监听器。尽可能直接使用值。
unforkEvent()
static unforkEvent(event: AnimatedEvent, listener: Function);
start()
static start(callback?: (result: {finished: boolean}) => void);
通过在动画上调用 start() 来启动动画。start() 接受一个完成回调,该回调将在动画完成时调用,或者在动画因在其完成之前调用 stop() 而完成时调用。
参数
姓名 | 类型 | 必需 | 描述 |
---|---|---|---|
callback | (result: {finished: boolean}) => void | 否 | 动画正常运行结束后,或者动画因在其完成之前调用 stop() 而结束后,将调用此函数。 |
带回调的启动示例
Animated.timing({}).start(({finished}) => {
/* completion callback */
});
stop()
static stop();
停止任何正在运行的动画。
reset()
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,用于将动画值附加到视图上的事件。如果可能,首选使用 Animated.event
和 useNativeDriver: true
。