Skip to content

Commit

Permalink
fix: ensure animations finish at target value (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
blaugold committed Sep 2, 2022
1 parent ebec2a9 commit 49126dc
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
22 changes: 16 additions & 6 deletions packages/fleet/lib/src/animation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ abstract class AnimationImpl<T> with Diagnosticable {
///
/// The returned [Duration] must be negative or zero and represents the
/// difference between when the animation reached its end value and [elapsed].
Duration? _isDone(Duration elapsed);
@protected
Duration? isAtEnd(Duration elapsed);

/// Returns the value of this animation at the given [elapsed] time.
///
Expand All @@ -303,7 +304,8 @@ abstract class AnimationImpl<T> with Diagnosticable {
/// actually returned value must always be assignable to [T] (if [T] is
/// nullable returning `null` is fine). See [AnimatableValue.createTween] for
/// more information.
T? _valueAt(Duration elapsed);
@protected
T? valueAt(Duration elapsed);

void _onTick(Duration elapsed) {
var elapsedForAllRepeats = elapsed * _spec._speed;
Expand All @@ -319,7 +321,7 @@ abstract class AnimationImpl<T> with Diagnosticable {
var elapsedForRepeat = elapsedForAllRepeats - _lastRepeatEnd;

if (_forward) {
final endDelta = _isDone(elapsedForRepeat);
final endDelta = isAtEnd(elapsedForRepeat);
if (endDelta != null) {
assert(endDelta.isNegative || endDelta.inMicroseconds == 0);
elapsedForRepeat = elapsedForRepeat + endDelta;
Expand All @@ -345,7 +347,15 @@ abstract class AnimationImpl<T> with Diagnosticable {
}
}

_currentValue = _valueAt(elapsedForRepeat) as T;
if (_isStopped) {
// On the last tick we need to be exactly at the end of the animation.
// If the animation is repeated and reversing it is possible that the
// last tick is at the beginning of the animation.
_currentValue = _tween.end as T;
} else {
_currentValue = valueAt(elapsedForRepeat) as T;
}

onChange?.call();
}

Expand Down Expand Up @@ -406,15 +416,15 @@ class _CurveAnimation<T> extends AnimationImpl<T> {
final _CurveAnimationProvider _provider;

@override
Duration? _isDone(Duration elapsed) {
Duration? isAtEnd(Duration elapsed) {
if (elapsed >= _provider.duration) {
return _provider.duration - elapsed;
}
return null;
}

@override
T? _valueAt(Duration elapsed) {
T? valueAt(Duration elapsed) {
var t = elapsed.inMicroseconds / _provider.duration.inMicroseconds;
t = _provider.curve.transform(t);
return _tween.transform(t);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,13 @@ void main() {
);

await tester.pump(d500ms); // .5
await tester.pump(d500ms); // 1.
await tester.pump(d500ms); // 1
await tester.pump(d500ms); // .5
await tester.pump(d500ms); // 0
await tester.pump(d250ms); // .25
await tester.pump(d250ms); // 1 (the last tick always goes to the end)
await tester.pumpAndSettle();

expect(state.animationChanges, [.5, 1, .5, 0]);
expect(state.animationChanges, [.5, 1, .5, .25, 1]);
});

testWidgets('3 times', (tester) async {
Expand All @@ -202,7 +203,7 @@ void main() {
);

await tester.pump(d500ms); // .5
await tester.pump(d500ms); // 1.
await tester.pump(d500ms); // 1
await tester.pump(d500ms); // .5
await tester.pump(d500ms); // 0
await tester.pump(d500ms); // .5
Expand Down

0 comments on commit 49126dc

Please sign in to comment.