数据绑定
数据绑定允许你将代码与 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 访问自动绑定的默认实例,无需使用 useViewModel 或 useViewModelInstance。
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 和用于更新它的函数(setValue、setRgb、trigger)。如果属性未 找到或 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 故事以获取演示。