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

相关推荐
任磊abc20 小时前
react native项目配置eslint+prettier
react native·eslint·prettier
YFF菲菲兔21 小时前
React 不冒泡的移入 / 移出事件插件
react.js
YFF菲菲兔21 小时前
React 表单控件 onChange 事件插件
react.js
濮水大叔1 天前
Hooks 之后,为什么前端仍需要“包裹”能力?
vue.js·react.js·前端框架
小粉粉hhh1 天前
React(三)——Redux
前端·javascript·react.js
YFF菲菲兔1 天前
React 基础事件插件
react.js
qq_529599381 天前
react js循环滚动
前端·javascript·react.js
索西引擎1 天前
【React】严格模式:开发阶段质量保障的静态分析机制
前端·react.js·前端框架
sTone873751 天前
类RN框架通过Service暴露卡片渲染能力给AI Chat
android·react native