动画
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
Animated 库旨在让动画效果流畅、强大,且构建和维护都轻松无忧。Animated 专注于输入与输出之间的声明式关系,提供可配置的中间转换过程,并通过 start/stop 方法控制基于时间的动画执行。
创建动画的核心流程是:创建 Animated.Value,将其关联到动画组件的一个或多个样式属性,然后通过 Animated.timing() 等动画方法驱动更新。
请勿直接修改动画值。你可以使用 useRef Hook 返回一个可变的 ref 对象。该 ref 对象的 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 线程执行动画,无需每帧都通过桥接通信。动画启动后,即使 JavaScript 线程阻塞也不会影响动画效果。
通过在动画配置中设置 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;
根据衰减系数使值从初始速度减速至零。
配置对象支持以下选项:
-
velocity: 初始速度(必需) -
deceleration: 衰减率(默认0.997) -
isInteraction:是否在InteractionManager上创建"交互句柄"。默认 true。 -
useNativeDriver:设置为 true 时启用原生驱动(必需项)。
timing()
static timing(value, config): CompositeAnimation;
沿时间缓动曲线对值进行动画处理。Easing模块提供多种预设曲线,也支持自定义函数。
配置对象支持以下选项:
-
duration:动画时长(毫秒)。默认值 500。 -
easing:定义运动曲线的缓动函数。默认为Easing.inOut(Easing.ease)。 -
delay:延迟启动动画的时间(毫秒)。默认值 0。 -
isInteraction:是否在InteractionManager上创建"交互句柄"。默认 true。 -
useNativeDriver:设置为 true 时启用原生驱动(必需项)。
spring()
static spring(value, config): CompositeAnimation;
基于阻尼简谐振动的物理弹簧模型驱动数值变化。通过追踪速度状态实现 toValue 更新时的流畅运动,支持链式调用。
配置对象包含以下选项:
注意:以下三组参数互斥(只能选择其中一组配置):
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:是否在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 解决。
配置对象支持以下选项:
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
);
配置对象支持以下选项:
-
listener:可选异步监听器。 -
useNativeDriver:设置为 true 时启用原生驱动(必需项)。
forkEvent()
static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;
高级命令式 API,用于监听通过 props 传入的动画事件。可在现有 AnimatedEvent 上添加新的 JavaScript 监听器:若 animatedEvent 已是 JavaScript 监听器,则合并两者;若 animatedEvent 为 null/undefined,则直接分配新监听器。建议优先直接使用值。
unforkEvent()
static unforkEvent(event: AnimatedEvent, listener: Function);
start()
static start(callback?: (result: {finished: boolean}) => void);
通过调用动画实例的 start() 方法启动动画。start() 接收完成回调函数,在动画正常结束或被 stop() 提前中断时触发。
参数:
| Name | Type | Required | Description |
|---|---|---|---|
| callback | (result: {finished: boolean}) => void | No | Function that will be called after the animation finished running normally or when the animation is done because stop() was called on it before it could finish |
带回调的启动示例:
Animated.timing({}).start(({finished}) => {
/* completion callback */
});
stop()
static stop();
停止任何正在运行的动画。
reset()
static reset();
停止任何正在运行的动画并将值重置为初始状态。
属性
Value
用于驱动动画的标准值类。通常在函数组件中初始化为 useAnimatedValue(0);,在类组件中初始化为 new Animated.Value(0);。
您可以在单独的页面上阅读有关 Animated.Value API 的更多信息。
ValueXY
用于驱动二维动画(如拖动手势)的二维值类。
您可以在单独的页面上阅读有关 Animated.ValueXY API 的更多信息。
Interpolation
导出用于在 flow 类型系统中使用插值类型。
Node
为方便类型检查而导出,所有动画值都继承自此类。
createAnimatedComponent
使任意 React 组件支持动画功能。用于创建 Animated.View 等组件。
attachNativeEvent
用于将动画值附加到视图事件的命令式 API。如有可能,建议优先使用 Animated.event 并设置 useNativeDriver: true。