You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:21:26