尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

React Native Skia 动图渲染实战:GIF 与动画 WebP 的 useAnimatedImageValue / useAnimatedImage 完整指南

发布时间:2026/9/25 3:15:44

资讯中心
01
ARTICLE

React Native Skia 动图渲染实战:GIF 与动画 WebP 的 useAnimatedImageValue / useAnimatedImage 完整指南

React Native Skia 动图渲染实战:GIF 与动画 WebP 的 useAnimatedImageValue / useAnimatedImage 完整指南
图形学移动开发跨平台UI组件【免费下载链接】react-native-skiaHigh-performance React Native Graphics using Skia项目地址https://gitcode.com/gh_mirrors/re/react-native-skia点击查看免费下载导读动画图片Animated Images是移动端 UI 中常见的高频需求例如加载占位、贴纸、表情或装饰性动效。React Native Skia 原生支持解码并播放GIF 与动画 WebP两种格式的动图本文将以 apps/docs/docs/animated-images.md 为核心主线系统讲解两条实践路径基于 Reanimated 的useAnimatedImageValue全自动播放方案以及更底层的useAnimatedImage手动逐帧控制 API。读完本文你将掌握动图的加载、按帧时长自动推进、暂停/恢复控制以及帧解码与内存释放的底层原理可直接在 Canvas 中集成会飞的 GIF、动态贴纸等效果。动图支持概览React Native Skia 的动图能力建立在 Skia 的SkAnimatedImage对象之上。它接收一份完整的编码数据encoded bytes内部持有解码器与当前帧指针可以按帧推进播放支持格式GIF、动画 WebP能力边界动图被解码为一个SkAnimatedImage实例每一帧通过getCurrentFrame()取回普通的SkImage再交给Image组件绘制平台差异原生端Android/iOS走 C 实现Web 端走 CanvasKitWASM实现二者对外暴露的 JS API 完全一致。在 JS 层SkAnimatedImage的工厂入口是Skia.AnimatedImage.MakeAnimatedImageFromEncoded(encoded)其类型定义见 AnimatedImageFactory.ts传入SkData解码成功返回动图对象字节无效时返回null。该对象初始即“指向”第一帧因此currentFrameDuration()与当前帧查询在创建后立即可用。方式一使用 Reanimated 的 useAnimatedImageValue全自动播放如果项目中已经集成了react-native-reanimated推荐使用官方提供的useAnimatedImageValueHook。它内部借助 Reanimated 的帧回调useFrameCallback自动完成逐帧解码与共享值更新使用者无需关心帧推进逻辑。基础用法加载并播放 GIFimport React from react; import { Canvas, Image, useAnimatedImageValue, } from shopify/react-native-skia; export const AnimatedImages () { // This can be an animated GIF or WebP file const bird useAnimatedImageValue( require(../../assets/birdFlying.gif) ); return ( Canvas style{{ width: 320, height: 180, }} Image image{bird} x{0} y{0} width{320} height{180} fitcontain / /Canvas ); };关键行为说明useAnimatedImageValue返回的是一个SharedValue初始值为null动图加载完成后每个渲染帧都会更新为一个SkImage对象直接传递给Image image{bird}即可实时绘制图片源通过require(...)传入动图资源会被打包进应用DataSourceParam类型既支持打包资源也支持远程地址与原始数据Image的fit属性本例为contain控制图片在 320×180 画布内的适配方式与静态图片完全一致。通过 SharedValue 控制暂停/恢复useAnimatedImageValue还接受第二个可选参数一个SharedValueboolean用于控制动画暂停状态。下面是点击屏幕暂停、再点恢复的完整示例import React from react; import {Pressable} from react-native; import {useSharedValue} from react-native-reanimated; import { Canvas, Image, useAnimatedImageValue, } from shopify/react-native-skia; export const AnimatedImages () { const isPaused useSharedValue(false); // This can be an animated GIF or WebP file const bird useAnimatedImageValue( require(../../assets/birdFlying.gif), isPaused ); return ( Pressable onPress{() isPaused.value !isPaused.value} Canvas style{{ width: 320, height: 180, }} Image image{bird} x{0} y{0} width{320} height{180} fitcontain / /Canvas /Pressable ); };由于暂停状态本身也是共享值这个能力可以非常自然地接入其它动画编排场景例如让动图在 Reanimated 动画进行时自动暂停、结束后恢复。底层实现剖析帧时长驱动与内存释放要理解useAnimatedImageValue的“自动”可以阅读其源码实现 useAnimatedImageValue.ts核心流程如下加载内部调用useAnimatedImage(source, onError)解码动图失败时抛出Could not load animated image - got ...错误帧时长读取取当前帧的currentFrameDuration()作为推进间隔若取不到则回退到默认值DEFAULT_FRAME_DURATION 60毫秒帧回调驱动在useFrameCallback中计算与上一帧的时间差elapsed当elapsed frameDuration时才调用decodeNextFrame()并读取新帧共享值更新与内存管理新帧写入currentFrame.value后立即对旧帧调用dispose()避免每一帧都驻留内存造成泄漏暂停逻辑isPaused.value为true时直接return动画停在当前帧恢复后继续推进。值得注意的是动图对象可能尚未加载完成异步解码此时帧回调会先把currentFrame.value置为null确保 UI 不会绘制无效图片。这套实现保证了帧推进严格按文件自带的帧间隔进行而非固定帧率、暂停不耗资源、旧帧及时回收。方式二手动 API —— useAnimatedImage 与 SkAnimatedImage对于需要完全掌控解码节奏的场景例如自定义播放速度、逐帧预览、帧跳转、与音视频同步React Native Skia 提供了手动 API。核心是useAnimatedImageHook它返回一个SkAnimatedImage对象而非共享值import {useAnimatedImage} from shopify/react-native-skia; // bird is an SkAnimatedImage const bird useAnimatedImage( require(../../assets/birdFlying.gif) )!; // SkAnimatedImage offers 4 methods: decodeNextFrame(), getCurrentFrame(), currentFrameDuration(), and getFrameCount() // getCurrentFrame() returns a regular SkImage const image bird.getCurrentFrame(); // decode the next frame bird.decodeNextFrame(); // fetch the current frame number const currentFrame bird.currentFrameDuration(); // fetch the total number of frames const frameCount bird.getFrameCount(); console.log({ frameCount, currentFrame, image });useAnimatedImage的实现见 AnimatedImage.ts它复用了useRawData将资源读取为原始字节后交给MakeAnimatedImageFromEncoded解码并支持传入onError回调处理加载失败。SkAnimatedImage 四个核心方法对应类型定义见 AnimatedImage.ts原生实现见 JsiSkAnimatedImage.h方法签名行为说明decodeNextFrame()(): number解码并推进到下一帧若已到最后一帧或发生错误返回-1kFinishedgetCurrentFrame()(): SkImage \| null返回当前帧对应的普通SkImage该SkImage一旦返回便不再变化无当前帧时返回nullcurrentFrameDuration()(): number返回当前帧需要显示的时长毫秒可据此决定何时推进下一帧getFrameCount()(): number返回动图总帧数可用于进度条、循环计数或预判资源规模原生端这 4 个方法均映射到 Skia C 的SkAnimatedImage接口getCurrentFrame()返回新包装的JsiSkImagegetFrameCount()透传SkAnimatedImage::getFrameCount()currentFrameDuration()透传currentFrameDuration()decodeNextFrame()透传decodeNextFrame()。手动驱动的常见模式手动 API 的典型用法是结合你自己的定时器或 Reanimated 工作流在合适时机调用// 自定义定时器驱动每帧显示 frameDuration 毫秒后推进 const intervalId setInterval(() { if (bird.decodeNextFrame() -1) { // 播放完毕可以重置或停止 } const frame bird.getCurrentFrame(); // 更新你的图片引用并重绘 }, bird.currentFrameDuration());需要注意的是手动模式下帧对象的内存回收由调用方负责。参考useAnimatedImageValue的做法每次切换到新帧后应当dispose()旧帧同时getCurrentFrame()返回的SkImage与动图对象生命周期绑定不要在动图对象释放后再使用该帧对象。动图解码在原生与 Web 端的落点为便于深入排查与二次开发这里给出动图能力在仓库中的关键实现位置JS 类型与工厂定义AnimatedImage/index.ts、AnimatedImage.ts、AnimatedImageFactory.ts原生C / JSI实现JsiSkAnimatedImage.h直接封装 Skia 的SkAnimatedImage与SkAndroidCodec解码链路WebCanvasKit实现JsiSkAnimatedImageFactory.ts调用CanvasKit.MakeAnimatedImageFromEncoded解码失败时返回nullReanimated 集成层useAnimatedImageValue.ts其中 Reanimated 通过模块代理ReanimatedProxy.ts按需引入——若项目未安装react-native-reanimated会抛出OptionalDependencyNotInstalledError提示这是一个可选依赖。这意味着useAnimatedImageValue仅在你已经使用 Reanimated 时才有意义如果项目没有 Reanimated请改用手动 APIuseAnimatedImage 自己的循环或者引入 Reanimated 后再使用自动播放方案。常见问题与注意事项动图不播放停在第一帧确认文件是 GIF 或动画 WebPMakeAnimatedImageFromEncoded对无效字节会返回null请检查资源路径与打包配置使用useAnimatedImageValue报“Reanimated 未安装”该 Hook 依赖react-native-reanimated需要先安装该可选依赖否则模块代理会抛出OptionalDependencyNotInstalledError内存持续增长手动模式下务必在切换到新帧后dispose()旧帧useAnimatedImageValue已内置此逻辑无需额外处理播放速率不匹配动图的帧间隔来自文件本身currentFrameDuration()不同 GIF 的帧率差异很大若需要统一节奏可在手动模式下自行换算时间暂停语义useAnimatedImageValue的paused参数接受任意SharedValueboolean暂停时帧回调直接返回不产生解码开销适合配合列表滚动等场景按需停播。总结React Native Skia 为动图提供了一条“一条指令接入、底层自动推进”的快捷路径useAnimatedImageValue Reanimated也保留了逐帧完全可控的手动 APIuseAnimatedImageSkAnimatedImage四方法。选择建议已有 Reanimated 依赖、追求开箱即用直接使用useAnimatedImageValue(source, paused?)注意内部已处理帧释放需要精细控制播放节奏或集成自定义播放器逻辑使用useAnimatedImage手动管理decodeNextFrame()与旧帧dispose()。两种方式共用同一套SkAnimatedImage解码内核无论在 Android、iOS 还是 Web 端行为一致可以放心在 Canvas 场景中把动图当作普通SkImage绘制、裁剪、做滤镜与混合。赞分享图形学移动开发跨平台UI组件【免费下载链接】react-native-skiaHigh-performance React Native Graphics using Skia项目地址https://gitcode.com/gh_mirrors/re/react-native-skia点击查看免费下载相关推荐流畅动画二选一Lottie-React-Native与React Native Skia渲染性能深度测评流畅动画二选一Lottie React Native与React Native Skia渲染性能深度测评 在移动应用开发中流畅的动画效果是提升用户体验的关键移动开发UI组件React Native Skia Skottie 实战指南Lottie 动画渲染、运行时属性修改与 Slot 槽位系统React Native Skia Skottie 实战指南Lottie 动画渲染、运行时属性修改与 Slot 槽位系统 Skottie 是构建在 Skia图形学移动开发跨平台UI组件BigImageViewer动图支持GIF和WebP动画图像完整解决方案BigImageViewer动图支持GIF和WebP动画图像完整解决方案 BigImageViewer是一个强大的Android大图查看库专门为GIF和We上一篇深入解析MLA 模式下的 llama-server 崩溃问题与排查修复下一篇SwiftNIO 贡献实践指南Bug 报告、Patch 规范、Swift 版本矩阵与 swift-format 格式化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。