跳到主要内容

数据绑定

数据绑定允许你将代码与 Rive 编辑器中绑定的元素连接起来。通过使用 View Model,你可以在编辑器中定义可绑定属性,然后在运行时通过 React Hook 读取和写入这些属性的值。

View Model

使用 useViewModel Hook 获取 View Model 的引用。你需要传入从 useRive 获取的 rive 对象。

import { useRive, useViewModel } from '@rive-app/react-webgl2';

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
// ... 其他选项
});

// 方式 1:获取画板的默认 ViewModel
const defaultViewModel = useViewModel(rive);

// 方式 2:显式获取默认 ViewModel
const defaultViewModelExplicit = useViewModel(rive, { useDefault: true });

// 方式 3:按名称获取 ViewModel
const namedViewModel = useViewModel(rive, { name: 'MyViewModelName' });

View Model 实例

使用 useViewModelInstance Hook 从 useViewModel Hook 返回的 View Model 创建 View Model 实例。

import { useRive, useViewModel, useViewModelInstance } from '@rive-app/react-webgl2';

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
// ... 其他选项
});

const viewModel = useViewModel(rive, { name: 'MyViewModelName' });
// 或:const viewModel = useViewModel(rive); // 默认 VM

// 获取默认实例,不绑定
const defaultUnbound = useViewModelInstance(viewModel, { useDefault: true });

// 获取命名实例,不绑定
const namedUnbound = useViewModelInstance(viewModel, { name: 'MyInstanceName' });

// 创建新的空白实例,不绑定
const newUnbound = useViewModelInstance(viewModel, { useNew: true });

你也可以通过向 useViewModelInstance Hook 传入 rive 对象,将 View Model 实例直接绑定到 Rive 实例。

import { useRive, useViewModel, useViewModelInstance } from '@rive-app/react-webgl2';

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: false, // 禁用自动绑定,以便稍后手动绑定
// ... 其他选项
});

const viewModel = useViewModel(rive, { name: 'MyViewModelName' });

// 获取默认实例(隐式)并绑定
const defaultBound = useViewModelInstance(viewModel, { rive });

// 获取命名实例并绑定
const namedBound = useViewModelInstance(viewModel, { name: 'MyInstanceName', rive });

// 创建新的空白实例并绑定
const newBound = useViewModelInstance(viewModel, { useNew: true, rive });

如果你在 useRive 中设置了 autoBind: true,一旦 Rive 加载完成,你可以直接通过 rive.viewModelInstance 访问自动绑定的默认实例,无需使用 useViewModeluseViewModelInstance

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: true,
});

// 加载完成后,实例即可用:
const boundInstance = rive?.viewModelInstance;

绑定

对于 React,无需额外步骤即可将 View Model 实例绑定到 Rive 组件。向 useViewModelInstance 传入 rive 对象会自动处理绑定。

自动绑定

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: true, // 启用自动绑定
// ... 其他选项
});

// 加载完成后,实例即可用:
const boundInstance = rive?.viewModelInstance;

属性

列出属性

// 从 useViewModel 返回的 View Model 访问属性
const viewModel = useViewModel(rive);
console.log(viewModel?.properties);

读取和写入属性

使用特定属性类型的 Hook 来获取和设置属性值。

  • useViewModelInstanceBoolean:读取/写入布尔属性
  • useViewModelInstanceString:读取/写入字符串属性
  • useViewModelInstanceNumber:读取/写入数字属性
  • useViewModelInstanceColor:读取/写入颜色属性,附带额外的 RGB/alpha 方法
  • useViewModelInstanceEnum:读取/写入枚举属性,附带可用值列表
  • useViewModelInstanceTrigger:触发事件,可选回调

这些 Hook 返回当前的 value 和用于更新它的函数(setValuesetRgbtrigger)。如果属性未找到或 Hook 接收了无效的 viewModelInstance,value 将为 null

import {
useViewModelInstanceBoolean,
useViewModelInstanceString,
useViewModelInstanceNumber,
useViewModelInstanceEnum,
useViewModelInstanceColor,
useViewModelInstanceTrigger
} from '@rive-app/react-webgl2';

// 假设 viewModelInstance 已通过 useViewModelInstance 或 rive.viewModelInstance 获取

// 布尔
const { value: isActive, setValue: setIsActive } = useViewModelInstanceBoolean(
'isToggleOn', // 属性路径
viewModelInstance
);
// 设置:setIsActive(true);

// 字符串
const { value: userName, setValue: setUserName } = useViewModelInstanceString(
'user/name', // 属性路径
viewModelInstance
);
// 设置:setUserName('Rive');

// 数字
const { value: score, setValue: setScore } = useViewModelInstanceNumber(
'levelScore', // 属性路径
viewModelInstance
);
// 设置:setScore(100);

// 枚举
const { value: status, setValue: setStatus, values: statusOptions } = useViewModelInstanceEnum(
'appStatus', // 属性路径
viewModelInstance
);
// 设置:setStatus('loading');
// 获取可用选项:statusOptions 是类似 ['idle', 'loading', 'error'] 的数组

// 颜色
const {
value: themeColor, // 原始数值,如 -3267805
setRgb: setThemeColorRgb, // 设置 RGB 分量(0-255 值)
setAlpha: setThemeColorAlpha, // 设置 Alpha 分量(0-255)
setOpacity: setThemeColorOpacity, // 设置不透明度(0.0-1.0)
setRgba: setThemeColorRgba, // 一次性设置所有分量
setValue: setThemeColorValue // 设置原始颜色值
} = useViewModelInstanceColor(
'ui/themeColor', // 属性路径
viewModelInstance
);
// 设置 RGB:setThemeColorRgb(0, 128, 255); // 设置为蓝色
// 设置 Alpha:setThemeColorAlpha(128); // 设置为 50% 不透明度
// 设置不透明度:setThemeColorOpacity(0.5); // 设置为 50% 不透明度
// 设置 RGBA:setThemeColorRgba(0, 128, 255, 255); // 蓝色,完全不透明
// 设置值:setThemeColorValue(-3267805); // 使用原始颜色值

// 触发器(无值,仅有触发函数)
const { trigger: playEffect } = useViewModelInstanceTrigger(
'playButtonEffect', // 属性路径
viewModelInstance,
{
// 可选回调,在触发器触发时调用
onTrigger: () => {
console.log('触发器已触发!');
}
}
);
// 触发:playEffect();

当 Rive 图形中的属性发生变化时,每个 Hook 返回的 value 会自动更新。

嵌套属性路径

通过将完整路径(以 / 分隔)作为属性 Hook 的第一个参数来访问嵌套属性。

import { useViewModelInstanceString, useViewModelInstanceNumber } from '@rive-app/react-webgl2';

// 访问 'settings/theme/name'(字符串)
const { value: themeName, setValue: setThemeName } = useViewModelInstanceString(
'settings/theme/name',
viewModelInstance
);

// 访问 'settings/volume'(数字)
const { value: volume, setValue: setVolume } = useViewModelInstanceNumber(
'settings/volume',
viewModelInstance
);

console.log('当前主题:', themeName);
// setThemeName('Dark Mode');
// setVolume(80);

可观察性

React Hook 自动处理可观察性。当属性值在 Rive 实例中发生变化时(无论是通过 Hook 设置还是由于内部绑定),相应 Hook(如 useViewModelInstanceString)返回的 value 会更新。此状态变化会触发 React 组件的重新渲染,使你能够响应新值。

对于触发器,你可以直接向 useViewModelInstanceTrigger Hook 提供 onTrigger 回调,该回调在 Rive 实例中激活触发器时触发。

import { useViewModelInstanceTrigger } from '@rive-app/react-webgl2';

// 假设 viewModelInstance 可用
const { trigger } = useViewModelInstanceTrigger(
'showPopup',
viewModelInstance,
{
onTrigger: () => {
console.log('显示弹窗触发器已触发!');
// 显示你的弹窗 UI
}
}
);

图片

使用 useViewModelInstanceImage Hook 设置 View Model 实例上的图片属性。

import { useRive, useViewModel, useViewModelInstance, useViewModelInstanceImage } from '@rive-app/react-webgl2';

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: false,
// ... 其他选项
});

const viewModel = useViewModel(rive, { name: 'MyViewModel' });
const viewModelInstance = useViewModelInstance(viewModel, { rive });

// 获取图片属性设置器
const { setValue: setImage } = useViewModelInstanceImage(
'profileImage', // 属性路径
viewModelInstance
);

// 加载并设置随机图片
const loadRandomImage = async () => {
if (!setImage) return;

try {
const imageUrl = 'https://picsum.photos/300/500';
const response = await fetch(imageUrl);
const imageBuffer = await response.arrayBuffer();

// 从响应中解码图片
const decodedImage = await decodeImage(new Uint8Array(imageBuffer));
setImage(decodedImage);

// 清理解码后的图片
decodedImage.unref();
} catch (error) {
console.error('加载图片失败:', error);
}
};

// 清除图片
const clearImage = () => {
if (setImage) {
setImage(null);
}
};

列表

使用 useViewModelInstanceList Hook 管理 View Model 实例上的列表属性。

import { useRive, useViewModel, useViewModelInstance, useViewModelInstanceList } from '@rive-app/react-webgl2';

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: false,
// ... 其他选项
});

const viewModel = useViewModel(rive, { name: 'MyViewModel' });
const viewModelInstance = useViewModelInstance(viewModel, { rive });

// 获取列表属性及操作函数
const {
length,
addInstance,
addInstanceAt,
removeInstance,
removeInstanceAt,
getInstanceAt,
swap
} = useViewModelInstanceList('todos', viewModelInstance);

// 添加新的待办事项
const handleAddItem = () => {
const todoItemViewModel = rive?.viewModelByName?.('TodoItem');
if (todoItemViewModel) {
const newTodoItem = todoItemViewModel.instance?.();
if (newTodoItem) {
// 设置一些初始值
newTodoItem.string('description').value = '购买食品杂货';
addInstance(newTodoItem);
}
}
};

// 在指定位置插入项目
const handleInsertItem = () => {
const todoItemViewModel = rive?.viewModelByName?.('TodoItem');
if (todoItemViewModel) {
const newTodoItem = todoItemViewModel.instance?.();
if (newTodoItem) {
addInstanceAt(newTodoItem, 0); // 插入到开头
}
}
};

// 按实例移除第一个项目
const handleRemoveFirst = () => {
const firstInstance = getInstanceAt(0);
if (firstInstance) {
removeInstance(firstInstance);
}
};

// 按索引移除项目
const handleRemoveAt = () => {
if (length > 0) {
removeInstanceAt(0);
}
};

// 交换两个项目
const handleSwap = () => {
if (length >= 2) {
swap(0, 1);
}
};

console.log(`列表共有 ${length}`);

画板

使用 useViewModelInstanceArtboard Hook 设置 View Model 实例上的画板属性。

import { useRive, useViewModel, useViewModelInstance, useViewModelInstanceArtboard } from '@rive-app/react-webgl2';

const { rive, RiveComponent } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: true,
// ... 其他选项
});

// 获取画板属性设置器
const { setValue: setArtboard1 } = useViewModelInstanceArtboard(
'artboard_1', // 属性路径
rive?.viewModelInstance
);

const { setValue: setArtboard2 } = useViewModelInstanceArtboard(
'artboard_2', // 属性路径
rive?.viewModelInstance
);

// 从同一文件中分配不同的画板
const handleSetBlueArtboard = () => {
if (rive) {
const blueArtboard = rive.getBindableArtboard('ArtboardBlue');
setArtboard1(blueArtboard);
}
};

const handleSetRedArtboard = () => {
if (rive) {
const redArtboard = rive.getBindableArtboard('ArtboardRed');
setArtboard2(redArtboard);
}
};

const handleSetGreenArtboard = () => {
if (rive) {
const greenArtboard = rive.getBindableArtboard('ArtboardGreen');
setArtboard1(greenArtboard);
}
};

枚举

const { rive } = useRive({
src: 'your_file.riv',
artboard: 'MyArtboard',
stateMachine: 'MyStateMachine',
autoBind: true
// ... 其他选项
});
const enums = rive?.enums();
console.log(enums);

示例

请参阅 Rive React 仓库 中的 DataBinding 故事以获取演示。