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. By default, RiveViewModel will automatically play the animation or state machine you’ve given it.

SwiftUI

struct AnimationView: View {
    var body: some View {
        RiveViewModel(
            fileName: "dancing_banana",
            animationName: "Charleston",
            artboardName: "Banana"
        ).view()
    }
}

UIKit

class AnimationViewController: UIViewController {
    @IBOutlet weak var riveView: RiveView!

    var bananaVM = RiveViewModel(
        fileName: "dancing_banana",
        animationName: "Charleston",
        artboardName: "Banana"
    )

    override func viewDidLoad() {
        bananaVM.setView(riveView)
    }
}

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

After creating a RiveViewModel, you can invoke animation playback control methods on a reference to this view model. Very often that will be all that is needed to display your Rive asset. However, we have some convenient controls for when you want more fine-grained control of when it plays and doesn’t. You can also choose the loop mode of the animation as additional parameters as needed. Along with playing animations, you similarly have the ability to pause, stop, and reset animation(s). Playing without
  • play(animationName: String? = nil, loop: Loop = .autoLoop, direction: Direction = .autoDirection)
    • animationName - Name of the animation to play
    • loop - Loop mode to play the animation in. Possible values listed below:
      • oneShot - plays animation through once
      • loop - plays through animation and repeats from the set starting time
      • pingPong - plays animation from start -> end, then end -> start on repeat
      • autoLoop (default) - plays through the loop setting set on the animation
    • direction - Direction to play the animation in
      • backwards - plays through animation timeline backward
      • forwards - plays through animation timeline forwards
      • autoDirection - plays through direction set on the animation
  • pause()
  • stop()
  • reset()

Play

If you set autoplay to false you can play the active animation or state machine very simply.
simpleVM.play()
If there are multiple animations on the active artboard you can play a specific one.
simpleVM.play(animationName: "Fancy Animation")

Pause/Stop/Reset

Based on certain events in your app you may want to adjust the playback further.
simpleVM.pause()
simpleVM.stop()
simpleVM.reset()

Player Delegates

This runtime allows for delegates that can be set on the RiveViewModel. You can use delegates to define functions that hook into when certain playback events are invoked. See the below class for how you can hook into the following playback events:
  • played
  • paused
  • stopped
  • advanced
  • animation looped
class ToggleViewModel: RiveViewModel {
  private let onAnimation: String = "On"
  private let offAnimation: String = "Off"
  private let startAnimation: String = "StartOff"

  var action: ((Bool) -> Void)? = nil
  var isOn = false {
      didSet {
          stop()
          play(animationName: isOn ? onAnimation : offAnimation)
          action?(isOn)
      }
  }

  init() {
      super.init(fileName: "toggle", animationName: startAnimation, fit: .cover)
  }

  func view(_ action: ((Bool) -> Void)? = nil) -> some View {
      self.action = action
      return super.view().frame(width: 100, height: 50, alignment: .center)
  }

  // When an animation is played
  override func player(playedWithModel riveModel: RiveModel?) {
    if let animationName = riveModel?.animation?.name() {...}
  }
  // When an animation is paused
  override func player(pausedWithModel riveModel: RiveModel?) {
    if let animationName = riveModel?.animation?.name() {...}
  }
  // When an animation is stopped
  override func player(stoppedWithModel riveModel: RiveModel?) {
    if let animationName = riveModel?.animation?.name() {...}
  }
  // When an animation is looped
  override func player(loopedWithModel riveModel: RiveModel?, type: Int) {
    if let animationName = riveModel?.animation?.name() {...}
  }
  // When an animation is advanced
  override func player(didAdvanceby seconds: Double, riveModel: RiveModel?) {...}
}