🔄

Rive に Data Binding がやってきた!アニメーション設計がもっと柔軟に!

に公開

ちょっと株式会社の KindBurger です!
本記事では、Rive に追加された Data Binding について紹介します!


おべんきょうして強くなるちょってぃ

※ Rive ってなに?という方は過去記事をご参照ください!
https://zenn.dev/chot/articles/9dfcfb0053ac6a

Data Binding とは?

Data Binding はアニメーション設計における柔軟性を大きく拡張する仕組みです!
主な特徴として、次の3点があります。(参考:公式の解説動画

1. プロパティ同士を連動させて制御できる

これまで、プロパティを連動させるにはステートマシンやコードでの HACK 的な工夫が必要でした。
Data Binding を使えば、あるプロパティの値を別のプロパティに直接関連づけて制御することが可能になります!
さらに、Converter を組み合わせることで、値に補正や変換を加えることも可能です!

次の例では、「ひまわりの種の x 座標」を用いて「ちょってぃの x 座標」を制御しています。

ひまわりの種を追いかけるちょってぃ

2. State machine の条件に任意のプロパティが使える

これまで、State machine の条件として使えるのは、主に Number・Boolean・Trigger の3種類の Inputs に限定されていました。
Data Binding では、View Model を通じて任意のプロパティ(例:X座標やスケールなど)の値をステートマシンの条件として扱えるようになり、動きや変化に応じたアニメーション制御が可能になります!

次の例では、「y 座標が一方より大きい」という条件で 👑 を表示しています。

カーレースするちょってぃ

3. ランタイムで任意のプロパティをコードから操作できる

これまで、Rive のランタイムでコードから操作できる値は、主に Inputs に限られていました。
Data Binding の登場により、View Model を通じて任意のプロパティにアクセスできる仕組みが加わり、コードから直接プロパティを読み書きしたり、その変化を監視して処理を実行することが可能になりました!

次の例では、コードから View Model を通じて Scale プロパティを直接操作しています。

巨大化するちょってぃ

Data Binding を使ってアニメーションを作ってみた!

それではデモ作業を通して Data Binding の機能を紹介します!

View Model でテキストを制御してみる

ここでは、View Model に String プロパティを持たせて、テキスト要素にバインドしてみます。

まずは View Model のイメージをざっくり押さえておきましょう:

  • View Model:データの集合体。OOP(オブジェクト指向プログラミング)でいう「クラス」
  • View Model Property:View Model の中のひとつのデータ。OOPでいう「フィールド」
  • View Model Instance:View Model の「実体」。OOPでいう「インスタンス」

それでは、実際に作成してみましょう!
まずは View Model を「Data」パネルから作成し、String プロパティ name を追加します:

続いて、Artboard に View Model を割り当て、Text Run に name をバインドします:
※ 右クリックで Data Biniding メニューが表示されます

State Machine のアニメーション再生を行うと、name の値がテキストに反映されるようになります!

Converter を使って Number プロパティをテキストに表示してみる

では次に、数値プロパティの値をテキストとして表示したいときはどうするでしょう?
実はそのままだと、Number プロパティとテキスト要素は直接バインドできません

そこで登場するのが、Converter(コンバーター) です。
Converter を使うことで、Number → String の変換処理を行い、バインドが可能になります!


それでは、実際に Converter を使ってみましょう!

View Model に Number プロパティ level を追加しておきます。
次に、テキスト要素と level をバインドしてみますが、そのままでは値が反映されません:

ここでConvert to String Converter を使って、数値を文字列に変換しましょう!
再生してみると、level の値がテキストに反映されるようになります!

Instance で複数の状態を扱ってみる

続いて紹介するのは、View Model Instance です!
ひとつの View Model から、異なる状態を持つ複数のインスタンスを作成し、個別に管理できます!

例えば、次のような UI を作るときに役立ちます:

  • プロフィール表示:共通のデザインを活かしつつ、ユーザーごとに名前・年齢などを切り替えて表示
  • アイコン付きボタン:アイコン、色、ラベル、アニメーション種別などを個別に表示・管理

どちらの例も、同じ構造をベースに内容や振る舞いだけを変えたい場面です。
Instance を活用すると、再利用性の高いアニメーション設計ができ、管理もしやすくなります!


それでは、実際に Instance を使ってみましょう!

事前に、Rank モデルを用意し、Number プロパティ requireLevel を追加しています。
また、テキスト要素にバインドして requireLevel の値を反映しています。

続いて、Instance を 3 つ作成してみましょう!

インスタンス名 requireLevel
junior 10
associate 20
senior 30

作成した Instance をそれぞれ Artboard に割り当てると、個別の状態が反映されています!

さらに、親となる View Model を用意することで、複数並べることもできます!
ここでは、複数の Rank Instance を内包する Main モデルを用意し、Nested Artboard にそれぞれ Instance を割り当てて作成しています!

View Model Property で State Machine を制御してみる

State Machine のアニメーション遷移条件として、View Model Property の値を設定することができます。
これにより、データの変化に応じてアニメーションを柔軟に切り替えることが可能になります。


それでは、実際にやってみましょう!

  • Character.level(現在のレベル)
  • Rank.requireLevel(必要なレベル)

この2つを比較し、level >= requireLevel のときにアニメーションを再生するように設定します。

親 Artboard で State Machine を再生すると、それぞれ条件を満たしたタイミングでアニメーションが発火します!

コードから View Model を操作してみる

最後に紹介するのは、コードから View Model を直接読み書きする方法です。
Data Binding を使うことで、アニメーションの状態やデータをコードから柔軟にコントロールすることが可能になります。

たとえば、次のようなことが可能になります:

  • ボタンのクリックに応じて、View Model の値を更新したりアニメーションを切り替える
  • 外部 API から取得したデータでアニメーション内容を変更する
  • View Model の値を監視し、変更時に処理を実行する

それでは実際に、Rive + React を使ってコードから View Model を操作してみましょう。

はじめにriv ファイルとしてエクスポートしたものを、@rive-app/react-canvas を用いて読み込みます。

https://www.npmjs.com/package/@rive-app/react-canvas

import {
  useRive,
  useViewModel,
  useViewModelInstance,
  useViewModelInstanceString,
  useViewModelInstanceTrigger,
} from "@rive-app/react-canvas";
import styles from "./index.module.css";

export function MyRiveComponent() {

  // 🌟 Rive ファイルの読み込み
  const { rive, RiveComponent } = useRive({
    src: "/choty_game_ui.riv",
    artboard: "Main",
    stateMachines: "State Machine 1",
    autoplay: true,
    autoBind: true, // 🌟 自動バインディング
  });

  return (
    <div className={styles.container}>
      <RiveComponent />
    </div>
  );
}

続いて、あらかじめ用意していた Trigger プロパティ Rank.rankUpTrigger を監視し、
発火されたタイミングで Character.jobTitle をコードから更新します!

  const { rive, RiveComponent } = useRive({
    // ...
  });

  // 🌟 View Model instance の参照を取得
  const viewModel = useViewModel(rive, { name: "Main" });
  const viewModelInstance = useViewModelInstance(viewModel, { rive });

  // 🌟 View Model Property のセッターを取得
  const { setValue: setJobTitle } = useViewModelInstanceString(
    "choty/jobTitle",
    viewModelInstance
  );

  // 🌟 Trigger の発火タイミングで、View Model Property の値を更新
  useViewModelInstanceTrigger("junior/rankUpTrigger", viewModelInstance, {
    onTrigger: () => {
      setJobTitle("ジュニア");
    },
  });
  useViewModelInstanceTrigger("associate/rankUpTrigger", viewModelInstance, {
    onTrigger: () => {
      setJobTitle("アソシエイト");
    },
  });
  useViewModelInstanceTrigger("senior/rankUpTrigger", viewModelInstance, {
    onTrigger: () => {
      setJobTitle("シニア");
    },
  });

ランタイムでコードから View Model Property の値を更新できています!

ふりかえり

本記事では、Rive に新しく追加された Data Binding の機能を紹介しました。
特に View Model Instance を活用することで、アニメーション構造をそのままに、異なる状態を柔軟に扱える点が大きな魅力です。
ぜひ活用してみてください!

また、MCP サポートも進行中とのことで、今後のアップデートにも注目です!

https://x.com/rive_app/status/1925573205215035398

参考

chot Inc. tech blog

Discussion