Animated
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 线程上执行动画,而无需在每一帧都通过桥接器。动画开始后,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 中的一个,但不能定义多个。
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
来解决此问题。
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;
用于侦听通过 props 传入的动画事件的高级命令式 API。它允许为现有的 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
。