Skip to main content
DEPRECATION NOTICE: This entire page documents the legacy Animation Playback system. For new projects: Use State Machines instead. For existing projects: Plan to migrate from direct animation control to State Machines as soon as possible. This content is provided for legacy support only.
Rive lets you specify what animations and state machines to mix and play and control the play/pause state of each animation. The term animations may collectively refer to both animations and state machines. In this section, we explore how to deal with specific animation playback, rather than state machines.
If you are trying to coordinate multiple animations’ playback at runtime, consider using a state machine instead to do this for you!

Choosing starting animations

Starting animations can also be chosen when Rive is instantiated. The first animation on the artboard may play if one is not provided, or a state machine is not set.
// Play the idle animation
export const Simple = () => (
  <Rive src="https://cdn.rive.app/animations/vehicles.riv" animations="idle" />
);

// With `useRive` Hook:
export default function Simple() {
  const { RiveComponent } = useRive({
    src: 'https://cdn.rive.app/animations/vehicles.riv',
    animations: ['idle'],
    autoplay: true,
  });

  return <RiveComponent />;
}

Controlling playback

Playback of each animation and state machine can be separately controlled. You can play and pause playback using the play , pause and stop methods, either passing in the names of the animations you want to affect or passing in nothing which will affect all instanced animations.

Invoking Playback Controls

Very similarly to Web, you can pass in Rive params and callbacks for certain animation events. See the Web tab for some examples of callbacks you can set. Additionally, you can use the rive object returned from the useRive hook to invoke playback controls. See the example below here: https://codesandbox.io/p/sandbox/adoring-sea-n7m59f
import { useState } from "react";
import { useRive, Layout, Fit } from "@rive-app/react-canvas";

export default function App() {
  const [truckButtonText, setTruckButtonText] = useState("Start Truck");
  const [wiperButtonText, setWiperButtonText] = useState("Start Wipers");

  // animation will show the first frame but not start playing
  const { rive, RiveComponent } = useRive({
    src: "https://cdn.rive.app/animations/vehicles.riv",
    artboard: "Jeep",
    layout: new Layout({ fit: Fit.Cover }),
    // Listen for play events to update button text
    onPlay: (event) => {
      const names = event.data;
      names.forEach((name) => {
        if (name === "idle") {
          setTruckButtonText("Stop Truck");
        } else if (name === "windshield_wipers") {
          setWiperButtonText("Stop Wipers");
        }
      });
    },
    // Listen for pause events to update button text
    onPause: (event) => {
      const names = event.data;
      names.forEach((name) => {
        if (name === "idle") {
          setTruckButtonText("Start Truck");
        } else if (name === "windshield_wipers") {
          setWiperButtonText("Start Wipers");
        }
      });
    },
  });

  function onStartTruckClick() {
    if (rive) {
      if (rive.playingAnimationNames.includes("idle")) {
        rive.pause("idle");
      } else {
        rive.play("idle");
      }
    }
  }

  function onStartWiperClick() {
    if (rive) {
      if (rive.playingAnimationNames.includes("windshield_wipers")) {
        rive.pause("windshield_wipers");
      } else {
        rive.play("windshield_wipers");
      }
    }
  }

  return (
    <>
      <div>
        <RiveComponent style={{ height: "1000px" }} />
      </div>
      <div>
        <button id="idle" onClick={onStartTruckClick}>
          {truckButtonText}
        </button>
        <button id="wipers" onClick={onStartWiperClick}>
          {wiperButtonText}
        </button>
      </div>
    </>
  );
}