加载资源
如果你想动态替换图像,请使用图像数据绑定。
某些 Rive 文件可能包含可以嵌入到实际文件二进制中的资源,例如字体、图像或音频文件。Rive 运行时可以在加载 Rive 文件时加载这些资源。虽然这样可以轻松使用 Rive 文件/运行时,但有时有机会在运行时加载这些资源甚至替换它们,而不是将它们嵌入文件二进制中。
这种方式有几个好处:
- 保持
.riv文件小巧,避免较大资源的潜在臃肿 - 根据任何原因动态加载资源,例如在移动设备上运行
.riv时加载较小分辨率的图像,而在桌面设备上加载较大分辨率的图像 - 预加载资源以便在显示
.riv时立即可用 - 使用已打 包在应用中的资源,如字体文件
- 在多个
.riv之间共享同一资源
加载资源的方法
目前有三种不同的方式来加载 Rive 文件的资源。
在 Rive 编辑器中,从资源选项卡中选择所需的资源,并在检查器中选择所需的导出选项:
嵌入式资源
在 Rive 编辑器中,通过选择「嵌入式」导出类型,可以将静态资源包含在 .riv 文件中。如本页开头所述,当 Rive 文件加载时,运行时会隐式尝试同时加载嵌入在 .riv 中的资源,你无需关心手动加载任何资源。
注意事项: 嵌入式资源可能会增大文件体积,尤其是在使用 Rive 文本(文本概述)时的字体方面。
嵌入是默认选项。
通过 Rive CDN 加载
在 Rive 编辑器中,你可以将导入的资源标记为「托管」导出类型,这意味着当你导出 .riv 文件时,资源不会嵌入到文件二进制中,而是托管在 Rive 的 CDN 上。这意味着在运行时加载文件时,运行时会看到资源被标记为「Hosted」并从 Rive CDN 加载资源,因此你无需自己加载任何内容,同时文件仍然保持小巧。
注意事项: 应用将额外调用 Rive CDN 来检索你的资源。
托管资源在 Voyager 和 Enterprise 计划中可用。了解更多关于我们的计划和定价。
图片 CDN
某些图片 CDN 允许实时图像转换,包括调整大小、裁剪和基于浏览器和设备能力的自动格式转换。这些 CDN 可以托管你的 Rive 图像资源。请注意,对于这些 CDN,你可能需要指定接受的格式,例如作为 HTTP 头部请求的一部分:
... headers: { Accept: 'image/png,image/webp,image/jpeg,*/*', } ...
请参阅你的 CDN 提供商的文档以获取更多信息。
⚠️ Rive 支持以下图像格式:jpeg、png 和 webp。
引用资源
在 Rive 编辑器中,你可以将导入的资源标记为「引用」导出类型,这意味着当你导出 .riv 文件时,资源不会嵌入到文件二进制中,加载资源的责任将由你的应用在运行时处理。
此选项允许你在运行时开始加载 .riv 文件时通过处理程序 API 动态加载资源。如果你需要根据任何应用/游戏逻辑动态加载特定资源,并且特别希望保持 .riv 文件大小小巧,则此选项更合适。
所有引用的资源,包括 .riv,将在你导出动画时打包为 zip 文件。
注意事项: 你需要在加载 Rive 时提供资源处理程序 API,负责自行加载资源。请参见下方的处理资源部分。
SVG 资源目前无法在运行时作为引用资源加载。
这是因为 SVG 会被转换为 Rive 矢量对象,它们总是嵌入到 .riv 文件中。
处理资源
示例
使用资源处理程序 API
在实例化新的 Rive 实例时,向参数列表中添加 assetLoader 回调属性。此回调将在运行时从 .riv 文件检测到的每个资源加载时被调用,并负责处理运行时资源的加载或传递责任给运行时以其他方式加载。
你可能需要处理资源加载的一个场景 是,如果文件中的资源标记为引用,并且你需要提供实际资源来渲染图形,因为 Rive 未将其嵌入 .riv 中,因此无法加载。
你可能希望让运行时处理资源加载的一个场景是,如果文件中的资源标记为托管,并希望将加载责任传递给运行时(运行时将调用 Rive CDN 来加载)。
assetLoader: (asset: rc.FileAsset, bytes: Uint8Array) => boolean;
你提供的回调将传递 asset 和 bytes。
asset— 来自 WASM 的FileAsset对象引用。你可以从此对象获取多个属性,例如名称、资源类型等。你还会用此对象为你想要动态加载的资源设置新的 Rive 特定资源(例如图像的RenderImage、字体的Font或音频的Audio)。bytes— 资源的字节数组(如果可用,比如它是嵌入式资源)。
重要提示: 注意返回值是一个 boolean,如果你打算自行处理加载资源,需要返回 true;如果你不希望自行处理该给定资源的加载,并尝试让运行时加载该资源,则返回 false。
在解码资源时,确保在不再需要时调用 unref,以避免内存泄漏。这允许引擎在该资源不再被任何动画使用时清理它。
示例用法
import {
Rive,
Fit,
Alignment,
Layout,
decodeFont,
ImageAsset, // 可选包含用于类型检查
FontAsset, // 可选包含用于类型检查
FileAsset, // 可选包含用于类型检查
} from "@rive-app/canvas";
// 通过使用 decodeFont API 加载随机资源,
// 并将其提供给 assetLoader 中提供的 asset 的 setFont API
const randomFontAsset = (asset) => {
const urls = [
"https://cdn.rive.app/runtime/flutter/IndieFlower-Regular.ttf",
"https://cdn.rive.app/runtime/flutter/comic-neue.ttf",
"https://cdn.rive.app/runtime/flutter/inter.ttf",
"https://cdn.rive.app/runtime/flutter/inter-tight.ttf",
"https://cdn.rive.app/runtime/flutter/josefin-sans.ttf",
"https://cdn.rive.app/runtime/flutter/send-flowers.ttf",
];
let randomIndex = Math.floor(Math.random() * urls.length);
fetch(urls[randomIndex]).then(
async (res) => {
// decodeFont 创建一个 Rive 特定的 Font 对象,该对象用于 assetLoader
// 中的 asset 的 `setFont()`
const font = await decodeFont(new Uint8Array(await res.arrayBuffer()));
asset.setFont(font);
// 确保在不再需要时对字体调用 unref。这允许引擎在
// 不再被任何动画使用时清理它。
font.unref();
}
);
};
const riveInstance = new Rive({
src: "acqua_text.riv",
stateMachines: "State Machine 1", // 要播放的状态机名称
canvas: document.getElementById("rive-canvas"),
layout: new Layout({
fit: Fit.Cover,
alignment: Alignment.Center,
}),
autoplay: true,
// 回调处理程序,指示如何处理正在加载的 Rive 文件中找到的资源
assetLoader: (asset, bytes) => {
console.log("Asset properties to query", {
name: asset.name,
fileExtension: asset.fileExtension,
cdnUuid: asset.cdnUuid,
isFont: asset.isFont,
isImage: asset.isImage,
isAudio: asset.isAudio,
bytes,
});
// 如果资源具有 `cdnUuid`,返回 false 让运行时处理从 CDN 加载
// 或者如果找到了资源的字节(即它是嵌入的),返回 false,因为此处不需要工作
if (asset.cdnUuid.length > 0 || bytes.length > 0) {
return false;
}
// 这里,我们在 Rive 文件加载时加载一个随机字体的字体资源
// 并返回 true,因为此回调处理程序负责加载资源,而非运行时
if (asset.isFont) {
randomFontAsset(asset);
return true;
}
},
onLoad: () => {
// 使用设备像素比防止 canvas 模糊
riveInstance.resizeDrawingSurfaceToCanvas();
}
});