animated_value.dart 4.24 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Adam Barth's avatar
Adam Barth committed
5
import 'dart:ui' show Color, Size, Rect;
6

7
import 'curves.dart';
8

Florian Loitsch's avatar
Florian Loitsch committed
9
/// The direction in which an animation is running.
10
enum AnimationDirection {
Florian Loitsch's avatar
Florian Loitsch committed
11
  /// The animation is running from beginning to end.
12
  forward,
13

Florian Loitsch's avatar
Florian Loitsch committed
14
  /// The animation is running backwards, from end to beginning.
15 16
  reverse
}
17

18
/// An interface describing a variable that changes as an animation progresses.
19
///
20 21 22
/// Animatable objects, by convention, must be cheap to create. This allows them
/// to be used in build functions in Widgets.
abstract class Animatable {
23
  // TODO(ianh): replace mentions of this class with just mentioning AnimatedValue directly
24
  /// Update the variable to a given time in an animation that is running in the given direction
25
  void setProgress(double t, AnimationDirection direction);
26 27
}

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
/// An animated variable with a concrete type.
class AnimatedValue<T extends dynamic> implements Animatable {
  AnimatedValue(this.begin, { this.end, this.curve, this.reverseCurve }) {
    value = begin;
  }

  /// The current value of this variable.
  T value;

  /// The value this variable has at the beginning of the animation.
  T begin;

  /// The value this variable has at the end of the animation.
  T end;

  /// Returns the value this variable has at the given animation clock value.
  T lerp(double t) => begin + (end - begin) * t;
45

Florian Loitsch's avatar
Florian Loitsch committed
46
  /// The curve to use in the forward direction.
47
  Curve curve;
48

Florian Loitsch's avatar
Florian Loitsch committed
49
  /// The curve to use in the reverse direction.
50
  ///
Florian Loitsch's avatar
Florian Loitsch committed
51
  /// If this field is null, uses [curve] in both directions.
52 53
  Curve reverseCurve;

54 55 56 57 58 59
  Curve _getActiveCurve(AnimationDirection direction) {
    if (direction == AnimationDirection.forward || reverseCurve == null)
      return curve;
    return reverseCurve;
  }

60
  double transform(double t, AnimationDirection direction) {
61 62 63
    Curve activeCurve = _getActiveCurve(direction);
    if (activeCurve == null)
      return t;
64
    if (t == 0.0 || t == 1.0) {
65
      assert(activeCurve.transform(t).round() == t);
66
      return t;
67
    }
68
    return activeCurve.transform(t);
69
  }
70

71 72
  /// Updates the value of this variable according to the given animation clock
  /// value and direction.
73
  void setProgress(double t, AnimationDirection direction) {
74
    if (end != null) {
75
      t = transform(t, direction);
76 77 78 79 80 81
      if (t == 0.0)
        value = begin;
      else if (t == 1.0)
        value = end;
      else
        value = lerp(t);
82 83 84 85 86 87
    }
  }

  String toString() => 'AnimatedValue(begin=$begin, end=$end, value=$value)';
}

88
/// An animated variable containing a color.
89 90 91
///
/// This class specializes the interpolation of AnimatedValue<Color> to be
/// appropriate for colors.
92
class AnimatedColorValue extends AnimatedValue<Color> {
93 94
  AnimatedColorValue(Color begin, { Color end, Curve curve, Curve reverseCurve })
    : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
95

Adam Barth's avatar
Adam Barth committed
96
  Color lerp(double t) => Color.lerp(begin, end, t);
97
}
98

99
/// An animated variable containing a size.
Adam Barth's avatar
Adam Barth committed
100
///
101
/// This class specializes the interpolation of AnimatedValue<Size> to be
Adam Barth's avatar
Adam Barth committed
102 103 104 105 106 107 108 109
/// appropriate for rectangles.
class AnimatedSizeValue extends AnimatedValue<Size> {
  AnimatedSizeValue(Size begin, { Size end, Curve curve, Curve reverseCurve })
    : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);

  Size lerp(double t) => Size.lerp(begin, end, t);
}

110
/// An animated variable containing a rectangle.
111 112 113
///
/// This class specializes the interpolation of AnimatedValue<Rect> to be
/// appropriate for rectangles.
114
class AnimatedRectValue extends AnimatedValue<Rect> {
115 116
  AnimatedRectValue(Rect begin, { Rect end, Curve curve, Curve reverseCurve })
    : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
117

Adam Barth's avatar
Adam Barth committed
118
  Rect lerp(double t) => Rect.lerp(begin, end, t);
119
}
120 121 122 123 124 125

/// An animated variable containing a int.
class AnimatedIntValue extends AnimatedValue<int> {
  AnimatedIntValue(int begin, { int end, Curve curve, Curve reverseCurve })
    : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);

Florian Loitsch's avatar
Florian Loitsch committed
126 127
  // The inherited lerp() function doesn't work with ints because it multiplies
  // the begin and end types by a double, and int * double returns a double.
128 129
  int lerp(double t) => (begin + (end - begin) * t).round();
}