-
Notifications
You must be signed in to change notification settings - Fork 470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Control Speed of Animation Programatically? #167
Comments
A recent issue touched a similar subject, you can take a look at this response |
We could also look into adding a speed multiplier to FlareActor. I worry that FlareActor is getting a little bloated. We'll be doing some writeups in the upcoming weeks that'll help devs understand how FlareActor works and help encourage you to write your own Flare widgets with special functionality. That'll help keep our codebase lean and unblock devs who want access to features like this without writing custom FlareActor controllers. |
@umberto-sonnino the related issue is a more complicated example of starting X time into an animation then playing to completion. I think we just want the ability to programmatically make sure an animation plays for a duration of X seconds. We can either do this, or spend lots of time editing our Flare animations to set the duration precisely. @luigi-rosso without adding a speed multiplier to FlareActor (which I agree is getting big), could you please provide some example code on how we might use FlareControls() to actually change just the elapsed/duration time for an animation. Perhaps it might be better to extend FlareControls, so we can specify a controller on FlareActor() and set the animation duration that way. But in the absence of that, we'd really appreciate example code to do what feels like a very basic function of animations we'd like to control programmatically. I was shocked to find this is not easy to do. With all the other great stuff flare can do ... this feels like a big gap in functionality. |
Here's a quick example of how a custom controller could do this: class SlowMoController extends FlareController {
final String animationName;
ActorAnimation _animation;
double speed;
double _time = 0;
SlowMoController(this.animationName, {this.speed = 1});
@override
bool advance(FlutterActorArtboard artboard, double elapsed) {
if (_animation == null) {
return false;
}
if (_animation.isLooping) {
_time %= _animation.duration;
}
_animation.apply(_time, artboard, 1.0);
_time += elapsed * speed;
// Stop advancing if animation is done and we're not looping.
return _animation.isLooping || _time < _animation.duration;
}
@override
void initialize(FlutterActorArtboard artboard) {
_animation = artboard.getAnimation(animationName);
}
@override
void setViewTransform(Mat2D viewTransform) {
// intentionally empty, we don't need the viewTransform in this controller
}
} You can instance that controller with an animation name and speed value, you can then change the speed value while the animation is playing back via a gesture callback in whatever widget holds the controller. class _SomeWidgetState extends State<SomeWidget> {
SlowMoController _controller = SlowMoController("idle", speed: 0.5);
@override
Widget build(BuildContext context) {
return FlareActor(
"assets/Filip.flr",
controller: _controller,
alignment: Alignment.center,
fit: BoxFit.contain,
);
}
} If you want to roll your own FlareControls with something similar added, take a look at this gist: https://gist.github.com/luigi-rosso/6c7b382efb925dc6feb9795ae38ae5be |
Thanks @luigi-rosso but I actually want to speed up the animation, not slow it down. So based on your example code above, even with speed: 2.0 (anything above 1.0) does not render anything on screen at all. Anything < 1.0 does play at reduced speed. I've been doing Flutter dev for 18 months, but note I'm having lots of trouble with getting to know Flare, mainly around the animation concepts which are a whole world in themselves. For example looking at your code, I really need an explanation of what exactly is 'mix' ??? Is the concept explained anywhere? See full code simplified example. Note the flare animation called "in" is valid:
|
Oh and the flare file is here: |
The mix value controls whether the incoming animation values get mixed over the existing values. Animations apply new values to existing ones. One good example is when you are mixing two animations together, like a run and a walk cycle. You might want to smoothly transition between the two, so you first apply your walk animation with mix 1 and then your run with a mix value between 0-1. This effectively lets you interpolate between animations (instead of just popping from one to another). This is more advanced functionality that is usually only used by custom controllers. I tried setting the speed to 2 and it's working here, I'll try with your file in a sec...The only thing I can think of is that it's a single shot (not looping) animation and it's completing before it fully draws a frame. |
I only see an "Untitled" animation in that file. I actually don't see anything in that file at all for some reason (regardless of which animation or controller is being used). Could you share the source by any chance? |
So its like an audio crossfade? Ok so I get the concept at a high level, but exactly does mix vary between the two animations, time? opacity of both animations? So if we have mix values for run and walk, how does 1 vs 0 - 1 apply? If we just cut from one to another is that equivalent to mix values of 1 and 1 ? I realise this is just second nature to you, but even as a dev having done animations in Flutter I still don't fully get it. I feel like this needs a diagram. btw. yes that animation is a single shot animation for approx. 2 seconds (not looping), so if I supply a speed of 2.0, I'd assume the duration was then approx. 1 second and so I'd expect to see something on screen for that 1 second. |
It's exactly like an audio crossfade! One way to wire up a controller is to basically act as a mixer for a bunch of animation channels. Regarding 0-1 it's essentially just like a lerp function, 0 means use only existing, and 1 means completely replace with incoming, anything in-between is interpolated. Every keyframed value gets affected (translation, rotation, color, opacity, constraint strengths, etc). |
So that flare file has Artboards for digits 0 - 9. Each artboard has "in", "out" and "Animations" animations. Note the digits are all imported Lottie files. Flare file is public here: https://www.2dimensions.com/a/mikeyman/files/flare/io-2018-digits |
btw. For background, I am trying to achieve the Google I/O app CountDown, which can be seen animating on this page about half way down: https://medium.com/androiddevelopers/animating-on-a-schedule-8a90d812ae4 |
Awesome! Ok so I tried it out, it seems to work for me, I'm not sure why you would see it with a value lower than 1 but not for one greater than 1. It only advances time once the animation is available, so I'm really stumped as to why you're not seeing it. Here's a video: https://drive.google.com/file/d/16UzC048sMQEf91-e_KeQcoGZCJzNnlAn/view?usp=sharing |
Thanks @luigi-rosso for taking such a close look. I'm stumped as well, so trying it on other emulators and devices now. Can you pls post your exact code, including pubspec.yaml. I might be able to spot any differences. btw. Im using packages flare_flutter: ^1.7.3 |
I put the full source here: https://github.com/luigi-rosso/flare_control_speed_example I'm also using flare_flutter 1.7.3 (you don't need to specify flare_dart, btw). I'm on Flutter master btw, not that it should make a difference...what channel are you on? |
Thanks I'll have a look at your code shortly. But I've been testing and it does work, but with some interesting results. So I thought I'd document as it may help. Just playing the "0" digit one-shot animation, but with speed: 2.0. When the "in" animation runs, it finishes showing the digit at the end.
... but if I increase the speed to say speed: 5.0 and run in release mode, then again it renders nothing again. So it definitely works @luigi-rosso thank you so much, but looks like there are some practical limits around timing depending on the speed of the device and how many times we multiple the speed up. Luckily I'll only be using a speed of about 2.0 to 2.5 to get the whole animation to work 👍I'll close the issue 😃 |
btw. I'm on flutter stable, so Flutter 1.9.1+hotfix.6. Had a look at your example code and its a nice example. Hopefully will help others too 😃👍 |
@luigi-rosso The speed example which is working great using your example code, but having an issue with it when animations are played one after another. Example full simplified code below (using your speed example code, but rename to SpeedController). I can play the first animation at slower/faster speed. But subsequent 'next' animations are not initialising properly and do not play. They show a new artboard 'digit' but do not animate, they simply show their last frame ie. the digit is shown but does not animate in. If I don't use the new SpeedController code and just use FlareActor() then it works fine, each digit animation plays.
|
How do you control the speed of the animation programatically?
If not currently possible can this feature be added?
The text was updated successfully, but these errors were encountered: