进阶 reactnative.dev 2026-10-11 06:04:21 · 22 阅读

第6章 React Native Animated 动画库详解

版本:0.77 # Animated Animated 库旨在让动画流畅、强大,同时易于构建和维护。它关注输入与输出之间的声明式关系、中间可配置的变换,以及控制基于时间动画执行的 start/stop 方法。 创建动画的核心流程是:先创建一个 Animated.Value,把它绑定到动画组件的一个或多个样式属性上,再通过 Animated.timing() 等动画方法驱动更新。 不要直接修改动画值。可以使用 useRef Hook 返回一个可变的 ref 对象,其 current 属性以传入的参数初始化,并在整个组件生命周期中保持不变。 ## 示例 下面的示例中,一个 View 会根据动画值 fadeAnim 实现淡入淡出效果。 更多 Animated 的实际用法可参考 Animations 指南。 ## 概览 Animated 提供两种值类型: - Animated.Value():单个值 - Animated.ValueXY():向量 Animated.Value 可以绑定到样式属性或其他 props,还支持插值。一个 Animated.Value 可以驱动任意多个属性。 ## 配置动画 Animated 提供三种动画类型,各自对应一种动画曲线,控制值如何从初始值过渡到最终值: - Animated.decay():以初始速度开始,逐渐减速直至停止。 - Animated.spring():提供基础的弹簧物理模型。 - Animated.timing():使用缓动函数随时间对值进行动画。 大多数情况下你会使用 timing()。它默认采用对称的 easeInOut 曲线,先让物体逐渐加速到全速,再逐渐减速直到停止。 ## 使用动画 调用动画的 start() 方法即可启动动画。start() 接受一个完成回调,在动画结束时调用。如果动画正常结束,回调会收到 {finished: true};如果动画因提前调用 stop() 而未完成(例如被手势或其他动画打断),则会收到 {finished: false}。 ```tsx Animated.timing({}).start(({finished}) => { /* completion callback */ }); ``` 使用原生驱动 采用原生驱动后,我们在动画开始前将所有动画参数发送给原生层,使原生代码得以在 UI 线程上执行动画,而无需每一帧都经过 Bridge。动画一旦启动,即使 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` 来将动画链接在一起。详见动画指南中关于跟踪动态值的内容。 默认情况下,如果组中的一个动画被停止或中断,组内其他所有动画也会随之停止。 组合动画值 可以通过加法、减法、乘法、除法或取模运算组合两个动画值,生成新的动画值: - `Animated.add()` - `Animated.subtract()` - `Animated.divide()` - `Animated.modulo()` - `Animated.multiply()` 插值 `interpolate()` 函数允许将输入范围映射到不同的输出范围。默认情况下,它会向给定范围之外外推曲线,但你也可以让它对输出值进行钳制。该函数默认使用线性插值,但也支持缓动函数。 interpolate() 有关插值的更多详情,请参阅动画指南。 处理手势及其他事件 使用 `Animated.event()` 可以将手势(如平移或滚动)及其他事件直接映射到动画值。这种映射采用结构化语法,以便从复杂的事件对象中提取值。第一层是一个数组,允许映射多个参数,该数组中包含嵌套对象。 Animated.event() 例如,在处理水平滚动手势时,要完成 `event.nativeEvent.contentOffset.x` 到 `scrollX`(一个 `Animated.Value`)的映射,应执行以下操作: React TSX onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{nativeEvent: {
contentOffset: {
x: scrollX
}
}
}]
)}
Reference 方法​ 如果传入的值是 ValueXY 而非 Value,每个配置项都可以是形如 {x: ..., y: ...} 的向量,而非标量。 decay()​ React TSX static decay(value, config): CompositeAnimation;
根据衰减系数,将数值从初始速度动画化至零。 Config 对象可包含以下选项: velocity: 初始速度。必填。 deceleration: 衰减率。默认 0.997。 isInteraction: 是否在 InteractionManager 上创建“交互句柄”。默认 true。 useNativeDriver: 为 true 时使用原生驱动。必填。 timing()​ React TSX static timing(value, config): CompositeAnimation;
沿定时缓动曲线对数值进行动画。Easing 模块内置大量预设曲线,你也可以自定义函数。 Config 对象可包含以下选项: duration: 动画时长(毫秒)。默认 500。 easing: 定义曲线的缓动函数。默认为 Easing.inOut(Easing.ease)。 delay: 延迟多少毫秒后开始动画。默认 0。 isInteraction: 是否在 InteractionManager 上创建“交互句柄”。默认 true。 useNativeDriver: 为 true 时使用原生驱动。必填。 spring()​ React TSX static spring(value, config): CompositeAnimation;

基于阻尼谐振荡的解析弹簧模型对数值进行动画处理。它会跟踪速度状态,让动画在 toValue 更新时依然保持流畅,并且可以链式组合。

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

注意,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:该动画是否在 InteractionManager 上创建“交互句柄”。默认值 true。

  • useNativeDriver:为 true 时使用原生驱动。必填。

add()​

React TSXstatic add(a: Animated, b: Animated): AnimatedAddition;
创建一个新的 Animated 值,等于两个 Animated 值相加。

subtract()​

React TSXstatic subtract(a: Animated, b: Animated): AnimatedSubtraction;
创建一个新的 Animated 值,等于第一个 Animated 值减去第二个 Animated 值。

divide()​

React TSXstatic divide(a: Animated, b: Animated): AnimatedDivision;

创建一个新 Animated 值,其值为第一个 Animated 值除以第二个 Animated 值。 multiply()​ React TSXstatic multiply(a: Animated, b: Animated): AnimatedMultiplication;
创建一个新 Animated 值,其值为两个 Animated 值相乘的结果。 modulo()​ React TSXstatic modulo(a: Animated, modulus: number): AnimatedModulo;
创建一个新 Animated 值,其值为给定 Animated 值的(非负)模。 diffClamp()​ React TSXstatic diffClamp(a: Animated, min: number, max: number): AnimatedDiffClamp;
创建一个新 Animated 值,其值被限制在两个数值之间。它基于与上一数值的差值进行计算,因此即使当前数值远超出边界,它也不会立即调整,而是等数值开始靠近边界时才发生变化。(公式:value = clamp(value + diff, min, max))。 此功能常用于滚动事件等场景,例如向上滚动时显示导航栏,向下滚动时隐藏导航栏。 delay()​ React TSXstatic delay(time: number): CompositeAnimation;
在指定延迟时间后启动动画。 sequence()​ React TSXstatic sequence(animations: CompositeAnimation[]): CompositeAnimation;
按顺序启动一组动画,等待当前动画完成后才启动下一个。如果当前正在运行的动画被停止,后续动画将不会启动。 parallel()​ React TSXstatic parallel(
animations: CompositeAnimation[],
config?: ParallelConfig
): CompositeAnimation;
同时启动一组动画。默认情况下,若其中一个动画被停止,所有动画都会随之停止。可通过 stopTogether 标志覆盖此行为。 stagger()​ React TSXstatic stagger(
time: number,
animations: CompositeAnimation[]
): CompositeAnimation;
一组动画可并行运行(存在重叠),但按顺序依次启动,每次启动之间设有递增的延迟。适用于创建拖尾效果。 loop()​ React TSXstatic loop(
animation: CompositeAnimation[],
config?: LoopAnimationConfig
): CompositeAnimation;
使指定动画循环播放。每次到达末尾后,动画会自动重置并从开头重新开始。若子动画配置了 `useNativeDriver: true`,动画循环将不会阻塞 JS 线程。此外,循环机制可以防止基于 VirtualizedList 的组件在动画运行期间渲染更多行;若在子动画配置中传入 `isInteraction: false` 即可修复此问题。 Config 对象支持以下选项: * `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}, ], // 手势状态参数 { listener: ( event: GestureResponderEvent, gestureState: PanResponderGestureState ) => console.log(event, gestureState), } // 可选的异步监听器 );` Config 对象支持以下选项: * `listener`:可选的异步监听器。 * `useNativeDriver`:当为 true 时启用原生驱动。此项为必填项。 forkEvent() React JSX `static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;` 这是用于拦截通过 props 传入的动画事件的高级命令式 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}) => {
/* completion callback */
});
stop()​ React TSX static stop();
停止正在运行的动画。 reset()​ React TSX static reset();
停止正在运行的动画,并将数值重置为初始值。 属性​ Value​ 用于驱动动画的标准数值类。通常通过 useAnimatedValue(0); 初始化,在 class 组件中则使用 new Animated.Value(0);。 关于 Animated.Value API 的更多内容可参阅单独的页面。 ValueXY​ 用于驱动二维动画(如拖拽手势)的二维数值类。 关于 Animated.ValueXY API 的更多内容可参阅单独的页面。 Interpolation​ 导出以便在 flow 中使用 Interpolation 类型。 Node​ 导出以便于类型检查。所有动画数值类都派生自该类。 createAnimatedComponent​ 让任意 React 组件支持动画。用于创建 Animated.View 等组件。 attachNativeEvent​ 命令式 API,用于将动画数值绑定到视图的某个事件上。如有可能,建议改用 Animated.event 并配合 useNativeDriver: true。

评论 (0)