RN 原生动画 Animated 用法、动画性能优化

📅 2026/7/19 3:15:23 👁️ 阅读次数 📝 编程学习
RN 原生动画 Animated 用法、动画性能优化

React Native 原生Animated是 RN 官方提供的动画库,适合实现大部分基础动画(淡入淡出、缩放、位移、旋转等)。如果是面试,通常会问两个方面:

  • Animated 的基本用法

  • 动画为什么会卡?如何优化?

下面按这两个方面总结。


一、Animated 基本用法

1. 创建动画值

const fadeAnim = useRef(new Animated.Value(0)).current;

Animated.Value 是动画驱动值。

例如:

0 -----> 1

表示透明度从 0 到 1。


2. Animated.View

普通 View 不能绑定 Animated.Value。

必须使用:

<Animated.View style={{ opacity: fadeAnim, }} />

3. timing 动画

最常见。

Animated.timing(fadeAnim, { toValue: 1, duration: 500, useNativeDriver: true, }).start();

参数:

参数作用
toValue目标值
duration动画时间
easing缓动函数
delay延迟
useNativeDriver是否使用原生驱动

4. spring 弹簧动画

Animated.spring(scale, { toValue: 1, friction: 4, tension: 80, useNativeDriver: true, }).start();

效果:

0.8 ↓ 1.1 ↓ 0.98 ↓ 1

适合:

  • Button点击

  • 卡片弹出

  • Drawer


5. decay

模拟惯性。

Animated.decay(position, { velocity: 2, deceleration: 0.998, useNativeDriver: true, }).start();

一般用于:

滑动 ↓ 松手继续滑

6. sequence

串行动画。

Animated.sequence([ Animated.timing(opacity,...), Animated.spring(scale,...) ]).start();

执行顺序:

透明 ↓ 缩放

7. parallel

并行动画。

Animated.parallel([ Animated.timing(opacity,...), Animated.spring(scale,...) ]).start();

同时执行。


8. stagger

交错动画。

Animated.stagger(100, animations).start();

效果:

Item1 100ms Item2 100ms Item3

9. loop

循环动画。

Animated.loop( Animated.timing(...) ).start();

例如 Loading。


二、插值 interpolate

Animated.Value 往往只有

0~1

需要转换。

例如:

const rotate = value.interpolate({ inputRange:[0,1], outputRange:["0deg","360deg"] })

再绑定:

transform:[ { rotate } ]

也可以:

0 ↓ 100px
translateX:value.interpolate({ inputRange:[0,1], outputRange:[0,100] })

三、Animated.event

绑定滚动。

const scrollY = useRef(new Animated.Value(0)).current; <Animated.ScrollView onScroll={Animated.event( [{ nativeEvent:{ contentOffset:{ y:scrollY } } }], { useNativeDriver:true } )} />

这样 Header 就能跟随 Scroll 做动画,而且使用原生驱动时不会因 JS 线程繁忙而明显掉帧。(React Native)


四、Animated 常见动画

例如透明:

opacity

位移:

translateX translateY

缩放:

scale

旋转:

rotate

组合:

transform:[ {translateY}, {scale}, {rotate} ]

五、为什么 Animated 会卡?

RN 有:

JS Thread ↓ Bridge ↓ Native(UI Thread)

如果:

JS执行太久

例如:

大量计算 网络回调 render setState

动画每一帧都要经过 Bridge 更新,就容易掉帧。


六、useNativeDriver 原理

默认:

JS ↓ 计算动画 ↓ Bridge ↓ Native

每一帧都要跨线程。

开启:

useNativeDriver:true

之后:

开始动画 ↓ 把动画配置发送给 Native ↓ Native 自己执行

动画运行过程中无需每帧经过 JS,因此即使 JS 线程短暂阻塞,动画仍能保持流畅。(React Native Archive)


七、为什么 useNativeDriver 更快?

因为:

没有 Bridge 通信

以前:

60FPS ↓ 60次Bridge

现在:

启动一次 ↓ Native执行

Bridge 开销几乎没有。


八、useNativeDriver 的限制

只能动画:

opacity transform translate scale rotate

不能:

width height left top flex margin

也就是说,布局属性通常不能由原生驱动直接动画。(React Native Archive)


九、动画性能优化

① 优先使用 useNativeDriver

Animated.timing(...,{ useNativeDriver:true })

这是官方推荐的首选优化。(React Native)


② 少动画 Layout

不要:

width height left top

推荐:

translate scale opacity

GPU 对transformopacity的处理通常更高效。(React Native Archive)


③ 避免频繁 setState

错误:

setState() ↓ render() ↓ 动画

改为:

Animated.Value

驱动 UI。


④ 减少组件重渲染

例如:

React.memo useMemo useCallback

动画组件不要反复 Render。


⑤ Scroll 动画使用 Animated.event

不要:

onScroll={()=>{ setState() }}

而是:

Animated.event(...)

减少 JS 参与,提高滚动跟随动画的流畅度。(React Native Archive)


⑥ 大列表不要全部动画

例如:

FlatList 1000 Item ↓ 1000 Animation

建议:

  • 仅为可见项添加动画

  • 配合FlatList的虚拟化能力

  • 避免长时间运行大量循环动画


⑦ 使用 Release 包测试

Debug 模式下:

JS很慢

不要拿 Debug 判断动画性能。


十、Animated 与 Reanimated 对比

对比项AnimatedReanimated
官方支持第三方(社区主流)
学习成本较高
useNativeDriver支持默认在 UI 线程执行工作单元
手势联动一般很强
复杂动画一般优秀
性能更好,尤其复杂交互场景

目前 React Native 社区中,如果涉及复杂手势、共享值、拖拽、布局动画等,很多项目更倾向于使用 Reanimated;而简单的透明度、位移、缩放等动画,官方Animated已经能够满足大多数需求。(SWMansion Docs)

面试总结(高频回答)

React Native 的Animated通过Animated.Value驱动动画,可使用timingspringsequenceparallelloop等 API 实现各种动画效果。性能优化的核心是尽量开启useNativeDriver,让动画在原生 UI 线程执行,减少 JS 线程和 Bridge 的参与;同时优先动画transformopacity,避免布局属性动画,减少组件重渲染,并在滚动场景使用Animated.event绑定事件,从而获得更流畅的 60 FPS 动画体验。(React Native)