Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added examples/public/data_binding_lists.riv
Binary file not shown.
Binary file added examples/public/global_variables_test.riv
Binary file not shown.
Binary file added examples/public/semantic_warning_exp4.riv
Binary file not shown.
17 changes: 17 additions & 0 deletions examples/src/components/DataBindingHooks.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react';

import GlobalViewModelInstance from './DataBindingHooks';

const meta = {
title: 'Data Binding - Globals (with hooks)',
component: GlobalViewModelInstance,
parameters: {
layout: 'fullscreen',
},
args: {},
} satisfies Meta<typeof GlobalViewModelInstance>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {};
77 changes: 77 additions & 0 deletions examples/src/components/DataBindingHooks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { useEffect } from 'react';
import {
useRive,
useViewModel,
useViewModelInstance,
useGlobalViewModelInstance,
useViewModelInstanceColor,
useViewModelInstanceString,
} from '@rive-app/react-webgl2';

/**
* Set up main + global view model data binding with hooks (autoBind: false).
*
* The hooks run shortly after Rive loads — so the first frame has already
* advanced and rendered before they bind. If you need data set before anything
* renders, see the "Globals (setup before first frame)" example (onRiveReady).
*/
const GLOBAL_VM_COLORS = 'Colors';
const COLOR_PROP = 'backgroundColor';

const GLOBAL_VM_CURRENCY = 'Labels';
const CURRENCY_PROP = 'currency';


const GlobalViewModelInstance = () => {
const { rive, RiveComponent } = useRive({
src: 'global_variables_test.riv',
stateMachines: 'State Machine 1',
autoplay: false,
autoBind: false,
});

// Set up the main view model instance if you need a reference to it to change any properties.
// These two lines are optional here: the global hooks below trigger a bind(), and bind() fills
// any unset slots (including main) with their default instance — so the default main gets bound
// either way. (With autoBind:false and no globals, you'd need to set the main yourself.)
const mainViewModel = useViewModel(rive, { name: 'Main' });
useViewModelInstance(mainViewModel, {rive});

// Set up global view model instances
// Note that we don't need to specify every global view model here - only the ones we want to have a reference to
// to change values on. The other globals will use a default instance.
const globalColorsViewModel = useViewModel(rive, { name: GLOBAL_VM_COLORS });
const globalColorsInstance = useGlobalViewModelInstance(
globalColorsViewModel,
GLOBAL_VM_COLORS,
{ rive }
);

const globalCurrencyViewModel = useViewModel(rive, { name: GLOBAL_VM_CURRENCY });
const globalCurrencyInstance = useGlobalViewModelInstance(
globalCurrencyViewModel,
GLOBAL_VM_CURRENCY,
{ rive }
);

const { value: bgColor, setValue: setBgColor } = useViewModelInstanceColor(
COLOR_PROP,
globalColorsInstance
);

const { value: currency, setValue: setCurrency } = useViewModelInstanceString(
CURRENCY_PROP,
globalCurrencyInstance
);

useEffect(() => {
setBgColor?.(parseInt('ff2266dd', 16));
setCurrency?.('USD');
// Play the animation again once the data is set
rive?.play();
}, [setBgColor, setCurrency, rive]);

return <RiveComponent />;
};

export default GlobalViewModelInstance;
17 changes: 17 additions & 0 deletions examples/src/components/DataBindingPreRender.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react';

import GlobalViewModels from './DataBindingPreRender';

const meta = {
title: 'Data Binding - Globals (setup before first frame)',
component: GlobalViewModels,
parameters: {
layout: 'fullscreen',
},
args: {},
} satisfies Meta<typeof GlobalViewModels>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {};
48 changes: 48 additions & 0 deletions examples/src/components/DataBindingPreRender.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import {
useRive,
ViewModelInstanceString,
ViewModel,
ViewModelInstance,
} from '@rive-app/react-webgl2';

/**
* Set up main + global view model data binding before the first frame renders,
* using onRiveReady — the synchronous window (before the state machine advances)
* where you can initialize instances so the graphic starts with your data.
*/
const GLOBAL_VM_NAME = 'Labels';
const CURRENCY_PROP = 'currency';

const GlobalViewModels = () => {
const { RiveComponent } = useRive({
src: 'global_variables_test.riv',
stateMachines: 'State Machine 1',
autoplay: true,
// set autoBind to false to set up main+global instances before first frame manually
autoBind: false,
onRiveReady: (r) => {
const mainVm = r?.viewModelByName('Main') as ViewModel;
const globalLabelsVm = r?.viewModelByName('Labels') as ViewModel;

if (mainVm) {
r.setViewModelInstance(mainVm.defaultInstance() as ViewModelInstance);
}
if (globalLabelsVm) {
const labelsInstance = globalLabelsVm.defaultInstance() as ViewModelInstance;
const currencyVal = labelsInstance.string(CURRENCY_PROP) as ViewModelInstanceString;
const alternateCurrencyVal = labelsInstance.string('alternateCurrency') as ViewModelInstanceString;
currencyVal.value = 'USD';
alternateCurrencyVal.value = '¥';

r.setGlobalViewModelInstance(GLOBAL_VM_NAME, labelsInstance);
}
// Flush the data binding setup for main+globals with bind()
r.bind();
},
});

return <RiveComponent />;
};

export default GlobalViewModels;
17 changes: 17 additions & 0 deletions examples/src/components/Semantics.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react';

import Semantics from './Semantics';

const meta = {
title: 'Semantics',
component: Semantics,
parameters: {
layout: 'fullscreen',
},
args: {},
} satisfies Meta<typeof Semantics>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {};
Loading
Loading