implements ActorAnimation Class
The ActorAnimation
is the class that handles a specific animation of a Rive Actor. You can access different properties of the specified animation to customize your Actor at runtime.
Duration allows you to obtain how long the animation will last, which is returned as a double:
getAnimation("name_of_Animation").duration
Looping is returned as a boolean to check whether an animation loops:
getAnimation("name_of_Animation").isLooping
FPS allows you to check an animation's frames per second, which is returned as an integer:
getAnimation("name_of_Animation").fps
The Rive Controller is a general-purpose interface for customizing the behavior of an animation at runtime. By extending the Controller
class you can override functions to have more control of the Rive Actor. This allows you access to things like being notified when an animation is complete, advancing through different states of an animation, etc. There are three main methods used when setting up a custom controller: initialize, advance and setViewTransform.
The initialize
method is called once when the controller is first created. Use it to fetch references to animation components that will be affected by the controller:
initialize(artboard)
The setViewTransform
method relays the information regarding the global viewTransform
matrix of the Actor that this controller is attached to. This is also called every frame, and relays information regarding the current view matrix of the animation.
setViewTransform(Mat2D viewTransform)
The advance
method will advance the animation of the current 'artboard' by elapsed
. It is called every frame. Every time the artboard advances, it relays the elapsed time to the controller, which can thus perform custom actions. This method's elapsed
parameter passes the time passed since the last frame. This must return a boolean.
bool advance(artboard, elapsed)
The current time of an animation can be manipulated at runtime inside of a custom controller. For example, in the advance
method you can achieve different effects (like animating a character to aim its weapon based on a mouse pointer) by dividing the entire length of the animation by another parameter such as elapsed time.
import 'package:flare_flutter/flare_actor.dart';import 'package:flare_flutter/flare_controller.dart';import 'package:flare_flutter/flare.dart';...ActorAnimation _myAnimation;​//modify this to change the filldouble _animTime = 0.00;double _currentAnimTime = 0;​void initialize(FlutterActorArtboard artboard) {_myAnimation= artboard.getAnimation("animationString");}bool advance(FlutterActorArtboard artboard, double elapsed) {_currentAnimTime +=(_animTime - _currentAnimTime) * min(1, elapsed * 5);​_myAnimation.apply(_currentAnimTime * _myAnimation.duration, artboard, 1);}...
open class CustomController: FlareSkViewController {open func onCompleted(name: String) {if(name == "AnimationName"){//Do Something}}override open func advanceControls(by elapsed: Double) -> Bool {guardlet fView = view as? FlareSkView,let artboard = fView.artboardelse { return false }return true;}override open func setViewTransform(viewTransform: Mat2D) {}..}
constructor(){super();this._ActorAnimator = null;this._CanPlay = false;this._AnimTime = 0;}initialize(artboard){this._ActorAnimator = this._Artboard.getAnimation("animationString");}advance(artboard, elapsed){this._AnimTime += elapsed *1;if (this._CanPlay === true){this._ActorAnimator.apply(this._AnimTime % this._ActorAnimator.duration, artboard, 1);}}
function FlareExample(canvas, ready){this._Graphics = new Flare.Graphics(canvas);this._Graphics.initialize("../build/", () =>{this._LastAdvanceTime = Date.now();this._ViewTransform = mat2d.create();this._AnimationInstance= null;​const _This = this;_ScheduleAdvance(_This);_Advance(_This);ready();});}function _Advance(_This){​_This.setSize(window.innerWidth, window.innerHeight);​const now = Date.now();const elapsed = (now - _This._LastAdvanceTime)/1000.0;_This._LastAdvanceTime = now;​const actor = _This._ActorInstance;if (_This._AnimationInstance){const ai = _This._AnimationInstance;ai.time = ai.time + elapsed;​ai.apply(_This._ActorInstance, 1.0);}if(actor){const graphics = _This._Graphics;const w = graphics.viewportWidth;const h = graphics.viewportHeight;​const vt = _This._ViewTransform;vt[0] = _Scale;vt[3] = _Scale;vt[4] = (-_ViewCenter[0] * _Scale + w/2);vt[5] = (-_ViewCenter[1] * _Scale + h/2);/** Advance the actor to its new time. */actor.advance(elapsed);}​_Draw(_This, _This._Graphics);/** Schedule a new frame. */_ScheduleAdvance(_This);}
...flare::ActorAnimation* animation = artboard->animation(animationName);...float animationTime = 0.0f;double time = glfwGetTime();float elapsed = (float)(time - lastTime);lastTime = time;​if (animation != nullptr){animationTime += elapsed;animation->apply(std::fmod(animationTime, animation->duration()), artboard, 1.0);}artboard->advance(elapsed);...
This is a blending parameter to allow smoothing between concurrent animations. By setting the mix to 1, the current animation will fully replace the existing values. By ramping up mix with values between 0 and 1, the transition from one animation to the next will be more gradual as it gets mixed in, preventing popping effects.
import 'package:flare_flutter/flare_controls.dart';...final FlareControls _flareControls = FlareControls();...{_flareControls.play("animationString", mix: 0.5, mixSeconds: 1.0);}
self.flareController!.play(name: "AnimationName", mix: 0.5, mixSeconds: 1.0)
import FlareComponent from 'flare-react';initialize(artboard){this._ActorAnimator = artboard.getAnimation("animation_String");}advance(artboard, elapsed){this._AnimTime += elapsed *1;this._ActorAnimator.apply(this._AnimTime % this._ActorAnimator.duration, artboard, 1);}
function FlareExample(canvas, ready){this._Graphics = new Flare.Graphics(canvas);this._Graphics.initialize("../build/", () =>{this._LastAdvanceTime = Date.now();this._ViewTransform = mat2d.create();this._AnimationInstance= null;​const _This = this;_ScheduleAdvance(_This);_Advance(_This);ready();});}function _Advance(_This){​_This.setSize(window.innerWidth, window.innerHeight);​const now = Date.now();const elapsed = (now - _This._LastAdvanceTime)/1000.0;_This._LastAdvanceTime = now;​const actor = _This._ActorInstance;if (_This._AnimationInstance){const ai = _This._AnimationInstance;//Apply Mix Time hereai.time = ai.time + elapsed;​ai.apply(_This._ActorInstance, 1.0);}if(actor){const graphics = _This._Graphics;const w = graphics.viewportWidth;const h = graphics.viewportHeight;​const vt = _This._ViewTransform;vt[0] = _Scale;vt[3] = _Scale;vt[4] = (-_ViewCenter[0] * _Scale + w/2);vt[5] = (-_ViewCenter[1] * _Scale + h/2);/** Advance the actor to its new time. */actor.advance(elapsed);}​_Draw(_This, _This._Graphics);/** Schedule a new frame. */_ScheduleAdvance(_This);}
coming soon
By defining a Rive controller in the Flutter and Swift runtimes, you can use the play("animationString")
method to give you more control over which animation is currently playing with out the need to create a custom controller class.
import 'package:flare_flutter/flare_controls.dart';...final FlareControls _flareControls = FlareControls();...{...child: FlareActor("assets/FlareFile.flr",controller: _flareControls),...}...{_flareControls.play("myAnimationName");}
private var flareController: FlareSkControls? = nil...override func viewDidLoad() {super.viewDidLoad()flareController = FlareSkControls(for: "FlareTest.flr", CGRect(x: 0, y: 0, width: frame.width, height: frame.height))flareController!.animationName = "Animation1"addChild(flareController!)}...self.flareController!.play(name: "Animation2", mix: 0.5, mixSeconds: 1.0)...
...flare::SkrActorArtboard* artboard = actor->artboard<flare::SkrActorArtboard>();artboard->initializeGraphics();​flare::ActorAnimation* animation = artboard->animation("animationString");...