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

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

  • Animated 的基本用法
  • 动画为什么会卡?如何优化?

下面按这两个方面总结。


一、Animated 基本用法

1. 创建动画值

ini 复制代码
const fadeAnim = useRef(new Animated.Value(0)).current;

Animated.Value 是动画驱动值。

例如:

lua 复制代码
0 -----> 1

表示透明度从 0 到 1。


2. Animated.View

普通 View 不能绑定 Animated.Value。

必须使用:

css 复制代码
<Animated.View
  style={{
    opacity: fadeAnim,
  }}
/>

3. timing 动画

最常见。

php 复制代码
Animated.timing(fadeAnim, {
  toValue: 1,
  duration: 500,
  useNativeDriver: true,
}).start();

参数:

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

4. spring 弹簧动画

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

效果:

复制代码
0.8
 ↓
1.1
 ↓
0.98
 ↓
1

适合:

  • Button点击
  • 卡片弹出
  • Drawer

5. decay

模拟惯性。

php 复制代码
Animated.decay(position, {
  velocity: 2,
  deceleration: 0.998,
  useNativeDriver: true,
}).start();

一般用于:

复制代码
滑动
↓

松手继续滑

6. sequence

串行动画。

scss 复制代码
Animated.sequence([
    Animated.timing(opacity,...),
    Animated.spring(scale,...)
]).start();

执行顺序:

复制代码
透明
↓

缩放

7. parallel

并行动画。

scss 复制代码
Animated.parallel([
    Animated.timing(opacity,...),
    Animated.spring(scale,...)
]).start();

同时执行。


8. stagger

交错动画。

scss 复制代码
Animated.stagger(100, animations).start();

效果:

复制代码
Item1

100ms

Item2

100ms

Item3

9. loop

循环动画。

scss 复制代码
Animated.loop(
    Animated.timing(...)
).start();

例如 Loading。


二、插值 interpolate

Animated.Value 往往只有

复制代码
0~1

需要转换。

例如:

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

再绑定:

css 复制代码
transform:[
    {
        rotate
    }
]

也可以:

复制代码
0
↓

100px
css 复制代码
translateX:value.interpolate({
    inputRange:[0,1],
    outputRange:[0,100]
})

三、Animated.event

绑定滚动。

php 复制代码
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 常见动画

例如透明:

css 复制代码
opacity

位移:

复制代码
translateX
translateY

缩放:

复制代码
scale

旋转:

复制代码
rotate

组合:

css 复制代码
transform:[
    {translateY},
    {scale},
    {rotate}
]

五、为什么 Animated 会卡?

RN 有:

scss 复制代码
JS Thread

↓

Bridge

↓

Native(UI Thread)

如果:

复制代码
JS执行太久

例如:

复制代码
大量计算

网络回调

render

setState

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


六、useNativeDriver 原理

默认:

arduino 复制代码
JS

↓

计算动画

↓

Bridge

↓

Native

每一帧都要跨线程。

开启:

vbnet 复制代码
useNativeDriver:true

之后:

复制代码
开始动画

↓

把动画配置发送给 Native

↓

Native 自己执行

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


七、为什么 useNativeDriver 更快?

因为:

没有 Bridge 通信

以前:

arduino 复制代码
60FPS

↓

60次Bridge

现在:

复制代码
启动一次

↓

Native执行

Bridge 开销几乎没有。


八、useNativeDriver 的限制

只能动画:

✅

css 复制代码
opacity

transform

translate

scale

rotate

不能:

css 复制代码
width

height

left

top

flex

margin

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


九、动画性能优化

① 优先使用 useNativeDriver

php 复制代码
Animated.timing(...,{
    useNativeDriver:true
})

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


② 少动画 Layout

不要:

css 复制代码
width

height

left

top

推荐:

css 复制代码
translate

scale

opacity

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


③ 避免频繁 setState

错误:

scss 复制代码
setState()

↓

render()

↓

动画

改为:

复制代码
Animated.Value

驱动 UI。


④ 减少组件重渲染

例如:

复制代码
React.memo

useMemo

useCallback

动画组件不要反复 Render。


⑤ Scroll 动画使用 Animated.event

不要:

scss 复制代码
onScroll={()=>{
    setState()
}}

而是:

csharp 复制代码
Animated.event(...)

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


⑥ 大列表不要全部动画

例如:

yaml 复制代码
FlatList

1000 Item

↓

1000 Animation

建议:

  • 仅为可见项添加动画
  • 配合 FlatList 的虚拟化能力
  • 避免长时间运行大量循环动画

⑦ 使用 Release 包测试

Debug 模式下:

复制代码
JS很慢

不要拿 Debug 判断动画性能。


十、Animated 与 Reanimated 对比

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

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

面试总结(高频回答)

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

相关推荐
传奇开心果编程16 小时前
【现代声明式UI学与练】第4课 列表渲染与 key——如何高效渲染列表、key 的作用、列表重排时的状态保持
学习·flutter·react native·ui·swiftui·android jetpack
太子釢18 小时前
React 函数组件与 Hook 实践指南
前端·react.js
liangshanbo121519 小时前
面试题:React 中 Lane 和 Scheduler 是怎么配合的?
前端·react.js·前端框架
liangshanbo121519 小时前
React面试题:Hooks 为什么不能在分支和循环里面写?
前端·javascript·react.js
FungLeo19 小时前
成为全栈·Next.js 网站前台篇·响应式、可访问性与错误状态:内容站不能只验桌面首页
react.js·响应式设计·next.js·移动端适配·成为全栈·web 可访问性
ss27320 小时前
AI全栈实战 | 3.5-01 Python 全栈前端最小集:不会 React 也能做出能看的后台,关键就一条线
前端·python·react.js
传奇开心果编程1 天前
【现代声明式UI学与练】第7课 组件通信——父传子、子传父、跨层级通信、状态提升与 Context
学习·flutter·react native·ui·swiftui·android jetpack
记得开心一点嘛2 天前
Trellora:基于 Electron、React 和本地知识库的 AI 知识工作台
人工智能·react.js·electron
500842 天前
React Native for OpenHarmony 实战:三方库 react-native-url-polyfill 的鸿蒙化适配指南
javascript·react native·react.js·性能优化·electron·harmonyos
传奇开心果编程2 天前
【现代声明式UI学与练】第9课 性能优化——渲染优化、列表优化、内存优化、启动优化
学习·flutter·react native·ui·性能优化·swiftui·android jetpack