Flutter-Rive中如何获取资源内的Nested Artboard?
Rive社区表情资源中Nested Artboard获取及单动画加载方案
核心逻辑
Rive官方运行时原生支持访问文件内所有嵌套Artboard,不需要拆解源文件,直接通过运行时API遍历匹配目标对象即可单独渲染,整体流程分3步:
- 加载riv文件后先获取主Artboard实例,不要直接初始化渲染
- 遍历主Artboard下的嵌套对象(多层嵌套需要递归遍历),匹配目标表情对应的Artboard
- 用匹配到的嵌套Artboard单独初始化Rive渲染实例,绑定对应动画/状态机即可独立使用
各端实现代码
Web端(基于@rive-app/canvas/webgl运行时)
import { Rive, Fit, Layout, Alignment } from '@rive-app/canvas'; // 加载本地riv资源 const riveBuffer = await fetch('/assets/animated-emojis.riv').then(res => res.arrayBuffer()); const tempRive = new Rive({ buffer: riveBuffer, autoplay: false, onLoad: () => { const rootArtboard = tempRive.artboard; let targetEmojiArtboard = null; // 递归遍历所有层级嵌套Artboard,避免多层分组漏找 const traverseNested = (artboard) => { for (let i = 0; i < artboard.nestedArtboardCount; i++) { const currentNested = artboard.nestedArtboard(i); // 首次调试时打开下面的日志,打印所有Artboard名称确认对应关系 // console.log('检测到嵌套Artboard:', currentNested.name); if (currentNested.name === '目标表情对应的Artboard名称') { targetEmojiArtboard = currentNested; return; } // 递归查当前嵌套下的子级 traverseNested(currentNested); } }; traverseNested(rootArtboard); tempRive.cleanup(); // 销毁临时实例,释放内存 if (!targetEmojiArtboard) throw new Error('未找到目标表情Artboard,请先打印所有嵌套对象确认名称'); // 单独渲染目标表情 new Rive({ canvas: document.getElementById('emoji-render-canvas'), artboard: targetEmojiArtboard, autoplay: true, stateMachines: ['默认状态机'], // 资源默认带的状态机一般命名为State Machine 1,可通过日志确认 layout: new Layout({ fit: Fit.Contain, alignment: Alignment.Center }) }); } });
Flutter端(基于rive官方dart包)
import 'package:rive/rive.dart'; import 'package:flutter/services.dart' show rootBundle; Future<Artboard?> loadTargetEmojiArtboard(String targetName) async { final riveData = await RiveFile.import( await rootBundle.load('assets/animated-emojis.riv') ); final rootArtboard = riveData.mainArtboard; Artboard? target; void traverse(Artboard board) { for (final nested in board.nestedArtboards) { // debugPrint('嵌套Artboard名称:${nested.name}'); if (nested.name == targetName) { target = nested.artboard; return; } traverse(nested.artboard); } } traverse(rootArtboard); return target; } // 组件内使用 final emojiArtboard = await loadTargetEmojiArtboard('目标表情Artboard名称'); if (emojiArtboard != null) { return Rive( artboard: emojiArtboard!, fit: BoxFit.contain, ); }
注意事项
- 第一次接入时一定要先打开遍历的日志打印,把所有嵌套Artboard的名称打出来,社区资源的命名、嵌套层级没有统一标准,不要靠猜写名称
- 用于遍历查找的临时Rive实例用完记得调用销毁/清理方法,避免内存占用
- 不要尝试手动解析riv二进制文件提取资源,官方API的兼容性最高,不会随文件版本升级失效
内容的提问来源于stack exchange,提问作者alexdotnet
相关产品推荐
相关产品推荐

