Commit 29d1d2ee authored by Adam Barth's avatar Adam Barth

Add more dartdoc to animation.dart

After the refactoring of the animation library, we were missing some
dartdoc.
parent df8c9714
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
/// The Flutter animation engine. /// The Flutter animation system.
///
/// See [https://flutter.io/animations/] for an overview.
/// ///
/// This library depends only on core Dart libraries and the `newton` package. /// This library depends only on core Dart libraries and the `newton` package.
library animation; library animation;
......
...@@ -30,15 +30,32 @@ enum AnimationStatus { ...@@ -30,15 +30,32 @@ enum AnimationStatus {
typedef void AnimationStatusListener(AnimationStatus status); typedef void AnimationStatusListener(AnimationStatus status);
/// An animation with a value of type T
///
/// An animation consists of a value (of type T) together with a status. The
/// status indicates whether the animation is conceptually running from
/// beginning to end or from the end back to the beginning, although the actual
/// value of the animation might not change monotonically (e.g., if the
/// animation uses a curve that bounces).
///
/// Animations also let other objects listen for changes to either their value
/// or their status. These callbacks are called during the "animation" phase of
/// the pipeline, just prior to rebuilding widgets.
///
/// To create a new animation that you can run forward and backward, consider
/// using [AnimationController].
abstract class Animation<T> { abstract class Animation<T> {
const Animation(); const Animation();
/// Calls the listener every time the value of the animation changes. /// Calls the listener every time the value of the animation changes.
void addListener(VoidCallback listener); void addListener(VoidCallback listener);
/// Stop calling the listener every time the value of the animation changes. /// Stop calling the listener every time the value of the animation changes.
void removeListener(VoidCallback listener); void removeListener(VoidCallback listener);
/// Calls listener every time the status of the animation changes. /// Calls listener every time the status of the animation changes.
void addStatusListener(AnimationStatusListener listener); void addStatusListener(AnimationStatusListener listener);
/// Stops calling the listener every time the status of the animation changes. /// Stops calling the listener every time the status of the animation changes.
void removeStatusListener(AnimationStatusListener listener); void removeStatusListener(AnimationStatusListener listener);
......
...@@ -13,8 +13,22 @@ import 'forces.dart'; ...@@ -13,8 +13,22 @@ import 'forces.dart';
import 'listener_helpers.dart'; import 'listener_helpers.dart';
import 'ticker.dart'; import 'ticker.dart';
/// A controller for an animation.
///
/// An animation controller can drive an animation forward or backward and can
/// set the animation to a particular value. The controller also defines the
/// bounds of the animation and can drive an animation using a physics
/// simulation.
class AnimationController extends Animation<double> class AnimationController extends Animation<double>
with EagerListenerMixin, LocalAnimationListenersMixin, LocalAnimationStatusListenersMixin { with EagerListenerMixin, LocalListenersMixin, LocalAnimationStatusListenersMixin {
/// Creates an animation controller.
///
/// * value is the initial value of the animation.
/// * duration is the length of time this animation should last.
/// * debugLabel is a string to help identify this animation during debugging (used by toString).
/// * lowerBound is the smallest value this animation can obtain and the value at which this animation is deemed to be dismissed.
/// * upperBound is the largest value this animation can obtain and the value at which this animation is deemed to be completed.
AnimationController({ AnimationController({
double value, double value,
this.duration, this.duration,
...@@ -22,10 +36,20 @@ class AnimationController extends Animation<double> ...@@ -22,10 +36,20 @@ class AnimationController extends Animation<double>
this.lowerBound: 0.0, this.lowerBound: 0.0,
this.upperBound: 1.0 this.upperBound: 1.0
}) { }) {
assert(upperBound >= lowerBound);
_value = (value ?? lowerBound).clamp(lowerBound, upperBound); _value = (value ?? lowerBound).clamp(lowerBound, upperBound);
_ticker = new Ticker(_tick); _ticker = new Ticker(_tick);
} }
/// Creates an animation controller with no upper or lower bound for its value.
///
/// * value is the initial value of the animation.
/// * duration is the length of time this animation should last.
/// * debugLabel is a string to help identify this animation during debugging (used by toString).
///
/// This constructor is most useful for animations that will be driven using a
/// physics simulation, especially when the physics simulation as no
/// pre-determined bounds.
AnimationController.unbounded({ AnimationController.unbounded({
double value: 0.0, double value: 0.0,
this.duration, this.duration,
...@@ -47,7 +71,7 @@ class AnimationController extends Animation<double> ...@@ -47,7 +71,7 @@ class AnimationController extends Animation<double>
/// identifying animation controller instances in debug output. /// identifying animation controller instances in debug output.
final String debugLabel; final String debugLabel;
/// Returns a [Animated<double>] for this animation controller, /// Returns an [Animated<double>] for this animation controller,
/// so that a pointer to this object can be passed around without /// so that a pointer to this object can be passed around without
/// allowing users of that pointer to mutate the AnimationController state. /// allowing users of that pointer to mutate the AnimationController state.
Animation<double> get view => this; Animation<double> get view => this;
...@@ -61,9 +85,9 @@ class AnimationController extends Animation<double> ...@@ -61,9 +85,9 @@ class AnimationController extends Animation<double>
Ticker _ticker; Ticker _ticker;
Simulation _simulation; Simulation _simulation;
/// The progress of this animation along the timeline. /// The current value of the animation.
/// ///
/// Note: Setting this value stops the current animation. /// Setting this value stops the current animation.
double get value => _value.clamp(lowerBound, upperBound); double get value => _value.clamp(lowerBound, upperBound);
double _value; double _value;
void set value(double newValue) { void set value(double newValue) {
...@@ -110,6 +134,7 @@ class AnimationController extends Animation<double> ...@@ -110,6 +134,7 @@ class AnimationController extends Animation<double>
_ticker.stop(); _ticker.stop();
} }
/// Stops running this animation.
void dispose() { void dispose() {
stop(); stop();
} }
...@@ -144,6 +169,7 @@ class AnimationController extends Animation<double> ...@@ -144,6 +169,7 @@ class AnimationController extends Animation<double>
_lastStatus = currentStatus; _lastStatus = currentStatus;
} }
/// Drives the animation from its current value to target.
Future animateTo(double target, { Duration duration, Curve curve: Curves.linear }) { Future animateTo(double target, { Duration duration, Curve curve: Curves.linear }) {
Duration simulationDuration = duration; Duration simulationDuration = duration;
if (simulationDuration == null) { if (simulationDuration == null) {
......
...@@ -8,8 +8,8 @@ import 'animation.dart'; ...@@ -8,8 +8,8 @@ import 'animation.dart';
import 'curves.dart'; import 'curves.dart';
import 'listener_helpers.dart'; import 'listener_helpers.dart';
class AlwaysCompleteAnimation extends Animation<double> { class _AlwaysCompleteAnimation extends Animation<double> {
const AlwaysCompleteAnimation(); const _AlwaysCompleteAnimation();
void addListener(VoidCallback listener) { } void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { } void removeListener(VoidCallback listener) { }
...@@ -20,10 +20,15 @@ class AlwaysCompleteAnimation extends Animation<double> { ...@@ -20,10 +20,15 @@ class AlwaysCompleteAnimation extends Animation<double> {
double get value => 1.0; double get value => 1.0;
} }
const AlwaysCompleteAnimation kAlwaysCompleteAnimation = const AlwaysCompleteAnimation(); /// An animation that is always complete.
///
/// Using this constant involves less overhead than building an
/// [AnimationController] with an initial value of 1.0. This is useful when an
/// API expects an animation but you don't actually want to animate anything.
const Animation<double> kAlwaysCompleteAnimation = const _AlwaysCompleteAnimation();
class AlwaysDismissedAnimation extends Animation<double> { class _AlwaysDismissedAnimation extends Animation<double> {
const AlwaysDismissedAnimation(); const _AlwaysDismissedAnimation();
void addListener(VoidCallback listener) { } void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { } void removeListener(VoidCallback listener) { }
...@@ -34,8 +39,14 @@ class AlwaysDismissedAnimation extends Animation<double> { ...@@ -34,8 +39,14 @@ class AlwaysDismissedAnimation extends Animation<double> {
double get value => 0.0; double get value => 0.0;
} }
const AlwaysDismissedAnimation kAlwaysDismissedAnimation = const AlwaysDismissedAnimation(); /// An animation that is always dismissed.
///
/// Using this constant involves less overhead than building an
/// [AnimationController] with an initial value of 0.0. This is useful when an
/// API expects an animation but you don't actually want to animate anything.
const Animation<double> kAlwaysDismissedAnimation = const _AlwaysDismissedAnimation();
/// An animation that is always stopped at a given value.
class AlwaysStoppedAnimation extends Animation<double> { class AlwaysStoppedAnimation extends Animation<double> {
const AlwaysStoppedAnimation(this.value); const AlwaysStoppedAnimation(this.value);
...@@ -49,8 +60,16 @@ class AlwaysStoppedAnimation extends Animation<double> { ...@@ -49,8 +60,16 @@ class AlwaysStoppedAnimation extends Animation<double> {
AnimationDirection get direction => AnimationDirection.forward; AnimationDirection get direction => AnimationDirection.forward;
} }
abstract class ProxyAnimatedMixin { /// Implements most of the [Animation] interface, by deferring its behavior to a
Animation<double> get parent; /// given [parent] Animation. To implement an [Animation] that proxies to a
/// parent, this class plus implementing "T get value" is all that is necessary.
abstract class ProxyAnimatedMixin<T> {
/// The animation whose value this animation will proxy.
///
/// This animation must remain the same for the lifetime of this object. If
/// you wish to proxy a different animation at different times, conside using
/// [ProxyAnimation].
Animation<T> get parent;
void addListener(VoidCallback listener) => parent.addListener(listener); void addListener(VoidCallback listener) => parent.addListener(listener);
void removeListener(VoidCallback listener) => parent.removeListener(listener); void removeListener(VoidCallback listener) => parent.removeListener(listener);
...@@ -61,8 +80,14 @@ abstract class ProxyAnimatedMixin { ...@@ -61,8 +80,14 @@ abstract class ProxyAnimatedMixin {
AnimationDirection get direction => parent.direction; AnimationDirection get direction => parent.direction;
} }
/// An animation that is a proxy for another animation.
///
/// A proxy animation is useful because the parent animation can be mutated. For
/// example, one object can create a proxy animation, hand the proxy to another
/// object, and then later change the animation from which the proxy receieves
/// its value.
class ProxyAnimation extends Animation<double> class ProxyAnimation extends Animation<double>
with LazyListenerMixin, LocalAnimationListenersMixin, LocalAnimationStatusListenersMixin { with LazyListenerMixin, LocalListenersMixin, LocalAnimationStatusListenersMixin {
ProxyAnimation([Animation<double> animation]) { ProxyAnimation([Animation<double> animation]) {
_parent = animation; _parent = animation;
if (_parent == null) { if (_parent == null) {
...@@ -76,6 +101,10 @@ class ProxyAnimation extends Animation<double> ...@@ -76,6 +101,10 @@ class ProxyAnimation extends Animation<double>
AnimationDirection _direction; AnimationDirection _direction;
double _value; double _value;
/// The animation whose value this animation will proxy.
///
/// This value is mutable. When mutated, the listeners on the proxy animation
/// will be transparently updated to be listening to the new parent animation.
Animation<double> get parent => _parent; Animation<double> get parent => _parent;
Animation<double> _parent; Animation<double> _parent;
void set parent(Animation<double> value) { void set parent(Animation<double> value) {
...@@ -121,10 +150,18 @@ class ProxyAnimation extends Animation<double> ...@@ -121,10 +150,18 @@ class ProxyAnimation extends Animation<double>
double get value => _parent != null ? _parent.value : _value; double get value => _parent != null ? _parent.value : _value;
} }
/// An animation that is the reverse of another animation.
///
/// If the parent animation is running forward from 0.0 to 1.0, this animation
/// is running in reverse from 1.0 to 0.0. Notice that using a ReverseAnimation
/// is different from simply using a [Tween] with a begin of 1.0 and an end of
/// 0.0 because the tween does not change the status or direction of the
/// animation.
class ReverseAnimation extends Animation<double> class ReverseAnimation extends Animation<double>
with LazyListenerMixin, LocalAnimationStatusListenersMixin { with LazyListenerMixin, LocalAnimationStatusListenersMixin {
ReverseAnimation(this.parent); ReverseAnimation(this.parent);
/// The animation whose value and direction this animation is reversing.
final Animation<double> parent; final Animation<double> parent;
void addListener(VoidCallback listener) { void addListener(VoidCallback listener) {
...@@ -169,7 +206,12 @@ class ReverseAnimation extends Animation<double> ...@@ -169,7 +206,12 @@ class ReverseAnimation extends Animation<double>
} }
} }
class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin { /// An animation that applies a curve to another animation.
///
/// [CurvedAnimation] is useful when you wish to apply a [Curve] and you already
/// have the underlying animation object. If you don't yet have an animation and
/// want to apply a [Curve] to a [Tween], consider using [CurveTween].
class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin<double> {
CurvedAnimation({ CurvedAnimation({
this.parent, this.parent,
this.curve: Curves.linear, this.curve: Curves.linear,
...@@ -180,6 +222,7 @@ class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin { ...@@ -180,6 +222,7 @@ class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin {
parent.addStatusListener(_handleStatusChanged); parent.addStatusListener(_handleStatusChanged);
} }
/// The animation to which this animation applies a curve.
final Animation<double> parent; final Animation<double> parent;
/// The curve to use in the forward direction. /// The curve to use in the forward direction.
...@@ -240,7 +283,7 @@ enum _TrainHoppingMode { minimize, maximize } ...@@ -240,7 +283,7 @@ enum _TrainHoppingMode { minimize, maximize }
/// removed, it exposes a [dispose()] method. Call this method to shut this /// removed, it exposes a [dispose()] method. Call this method to shut this
/// object down. /// object down.
class TrainHoppingAnimation extends Animation<double> class TrainHoppingAnimation extends Animation<double>
with EagerListenerMixin, LocalAnimationListenersMixin, LocalAnimationStatusListenersMixin { with EagerListenerMixin, LocalListenersMixin, LocalAnimationStatusListenersMixin {
TrainHoppingAnimation(this._currentTrain, this._nextTrain, { this.onSwitchedTrain }) { TrainHoppingAnimation(this._currentTrain, this._nextTrain, { this.onSwitchedTrain }) {
assert(_currentTrain != null); assert(_currentTrain != null);
if (_nextTrain != null) { if (_nextTrain != null) {
...@@ -261,11 +304,13 @@ class TrainHoppingAnimation extends Animation<double> ...@@ -261,11 +304,13 @@ class TrainHoppingAnimation extends Animation<double>
assert(_mode != null); assert(_mode != null);
} }
/// The animation that is current driving this animation.
Animation<double> get currentTrain => _currentTrain; Animation<double> get currentTrain => _currentTrain;
Animation<double> _currentTrain; Animation<double> _currentTrain;
Animation<double> _nextTrain; Animation<double> _nextTrain;
_TrainHoppingMode _mode; _TrainHoppingMode _mode;
/// Called when this animation switches to be driven by a different animation.
VoidCallback onSwitchedTrain; VoidCallback onSwitchedTrain;
AnimationStatus _lastStatus; AnimationStatus _lastStatus;
...@@ -298,6 +343,9 @@ class TrainHoppingAnimation extends Animation<double> ...@@ -298,6 +343,9 @@ class TrainHoppingAnimation extends Animation<double>
_currentTrain.removeStatusListener(_statusChangeHandler); _currentTrain.removeStatusListener(_statusChangeHandler);
_currentTrain.removeListener(_valueChangeHandler); _currentTrain.removeListener(_valueChangeHandler);
_currentTrain = _nextTrain; _currentTrain = _nextTrain;
// TODO(hixie): This should be setting a status listener on the next
// train, not a value listener, and it should pass in _statusChangeHandler,
// not _valueChangeHandler
_nextTrain.addListener(_valueChangeHandler); _nextTrain.addListener(_valueChangeHandler);
_statusChangeHandler(_nextTrain.status); _statusChangeHandler(_nextTrain.status);
} }
......
...@@ -10,6 +10,7 @@ export 'package:newton/newton.dart' show SpringDescription; ...@@ -10,6 +10,7 @@ export 'package:newton/newton.dart' show SpringDescription;
abstract class Force { abstract class Force {
const Force(); const Force();
/// Creates a new physics simulation with the given initial conditions.
Simulation release(double position, double velocity); Simulation release(double position, double velocity);
} }
......
...@@ -11,6 +11,7 @@ abstract class _ListenerMixin { ...@@ -11,6 +11,7 @@ abstract class _ListenerMixin {
void didUnregisterListener(); void didUnregisterListener();
} }
/// A mixin that helps listen to another object only when this object has registered listeners.
abstract class LazyListenerMixin implements _ListenerMixin { abstract class LazyListenerMixin implements _ListenerMixin {
int _listenerCounter = 0; int _listenerCounter = 0;
void didRegisterListener() { void didRegisterListener() {
...@@ -30,6 +31,8 @@ abstract class LazyListenerMixin implements _ListenerMixin { ...@@ -30,6 +31,8 @@ abstract class LazyListenerMixin implements _ListenerMixin {
bool get isListening => _listenerCounter > 0; bool get isListening => _listenerCounter > 0;
} }
/// A mixin that replaces the didRegisterListener/didUnregisterListener contract
/// with a dispose contract.
abstract class EagerListenerMixin implements _ListenerMixin { abstract class EagerListenerMixin implements _ListenerMixin {
void didRegisterListener() { } void didRegisterListener() { }
void didUnregisterListener() { } void didUnregisterListener() { }
...@@ -38,7 +41,9 @@ abstract class EagerListenerMixin implements _ListenerMixin { ...@@ -38,7 +41,9 @@ abstract class EagerListenerMixin implements _ListenerMixin {
void dispose(); void dispose();
} }
abstract class LocalAnimationListenersMixin extends _ListenerMixin { /// A mixin that implements the addListener/removeListener protocol and notifies
/// all the registered listeners when notifyListeners is invoked.
abstract class LocalListenersMixin extends _ListenerMixin {
final List<VoidCallback> _listeners = <VoidCallback>[]; final List<VoidCallback> _listeners = <VoidCallback>[];
void addListener(VoidCallback listener) { void addListener(VoidCallback listener) {
didRegisterListener(); didRegisterListener();
...@@ -55,6 +60,9 @@ abstract class LocalAnimationListenersMixin extends _ListenerMixin { ...@@ -55,6 +60,9 @@ abstract class LocalAnimationListenersMixin extends _ListenerMixin {
} }
} }
/// A mixin that implements the addStatusListener/removeStatusListener protocol
/// and notifies all the registered listeners when notifyStatusListeners is
/// invoked.
abstract class LocalAnimationStatusListenersMixin extends _ListenerMixin { abstract class LocalAnimationStatusListenersMixin extends _ListenerMixin {
final List<AnimationStatusListener> _statusListeners = <AnimationStatusListener>[]; final List<AnimationStatusListener> _statusListeners = <AnimationStatusListener>[];
void addStatusListener(AnimationStatusListener listener) { void addStatusListener(AnimationStatusListener listener) {
......
...@@ -8,21 +8,27 @@ import 'animation.dart'; ...@@ -8,21 +8,27 @@ import 'animation.dart';
import 'animations.dart'; import 'animations.dart';
import 'curves.dart'; import 'curves.dart';
/// An object that can produce a value of type T given an [Animation] as input.
abstract class Animatable<T> { abstract class Animatable<T> {
const Animatable(); const Animatable();
/// The current value of this object for the given animation.
T evaluate(Animation<double> animation); T evaluate(Animation<double> animation);
/// Returns a new Animation that is driven by the given animation but that
/// takes on values determined by this object.
Animation<T> animate(Animation<double> parent) { Animation<T> animate(Animation<double> parent) {
return new _AnimatedEvaluation<T>(parent, this); return new _AnimatedEvaluation<T>(parent, this);
} }
/// Returns a new Animatable whose value is determined by first evaluating
/// the given parent and then evaluating this object.
Animatable<T> chain(Animatable<double> parent) { Animatable<T> chain(Animatable<double> parent) {
return new _ChainedEvaluation<T>(parent, this); return new _ChainedEvaluation<T>(parent, this);
} }
} }
class _AnimatedEvaluation<T> extends Animation<T> with ProxyAnimatedMixin { class _AnimatedEvaluation<T> extends Animation<T> with ProxyAnimatedMixin<double> {
_AnimatedEvaluation(this.parent, this._evaluatable); _AnimatedEvaluation(this.parent, this._evaluatable);
/// The animation from which this value is derived. /// The animation from which this value is derived.
...@@ -45,6 +51,7 @@ class _ChainedEvaluation<T> extends Animatable<T> { ...@@ -45,6 +51,7 @@ class _ChainedEvaluation<T> extends Animatable<T> {
} }
} }
/// A linear interpolation between a beginning and ending value.
class Tween<T extends dynamic> extends Animatable<T> { class Tween<T extends dynamic> extends Animatable<T> {
Tween({ this.begin, this.end }); Tween({ this.begin, this.end });
...@@ -57,6 +64,7 @@ class Tween<T extends dynamic> extends Animatable<T> { ...@@ -57,6 +64,7 @@ class Tween<T extends dynamic> extends Animatable<T> {
/// Returns the value this variable has at the given animation clock value. /// Returns the value this variable has at the given animation clock value.
T lerp(double t) => begin + (end - begin) * t; T lerp(double t) => begin + (end - begin) * t;
/// Returns the interpolated value for the current value of the given animation.
T evaluate(Animation<double> animation) { T evaluate(Animation<double> animation) {
if (end == null) if (end == null)
return begin; return begin;
...@@ -69,7 +77,7 @@ class Tween<T extends dynamic> extends Animatable<T> { ...@@ -69,7 +77,7 @@ class Tween<T extends dynamic> extends Animatable<T> {
} }
} }
/// An animated variable containing a color. /// An interpolation between two colors.
/// ///
/// This class specializes the interpolation of Tween<Color> to be /// This class specializes the interpolation of Tween<Color> to be
/// appropriate for colors. /// appropriate for colors.
...@@ -79,7 +87,7 @@ class ColorTween extends Tween<Color> { ...@@ -79,7 +87,7 @@ class ColorTween extends Tween<Color> {
Color lerp(double t) => Color.lerp(begin, end, t); Color lerp(double t) => Color.lerp(begin, end, t);
} }
/// An animated variable containing a size. /// An interpolation between two sizes.
/// ///
/// This class specializes the interpolation of Tween<Size> to be /// This class specializes the interpolation of Tween<Size> to be
/// appropriate for rectangles. /// appropriate for rectangles.
...@@ -89,7 +97,7 @@ class SizeTween extends Tween<Size> { ...@@ -89,7 +97,7 @@ class SizeTween extends Tween<Size> {
Size lerp(double t) => Size.lerp(begin, end, t); Size lerp(double t) => Size.lerp(begin, end, t);
} }
/// An animated variable containing a rectangle. /// An interpolation between two rectangles.
/// ///
/// This class specializes the interpolation of Tween<Rect> to be /// This class specializes the interpolation of Tween<Rect> to be
/// appropriate for rectangles. /// appropriate for rectangles.
...@@ -99,7 +107,11 @@ class RectTween extends Tween<Rect> { ...@@ -99,7 +107,11 @@ class RectTween extends Tween<Rect> {
Rect lerp(double t) => Rect.lerp(begin, end, t); Rect lerp(double t) => Rect.lerp(begin, end, t);
} }
/// An animated variable containing a int. /// An interpolation between two integers.
///
/// This class specializes the interpolation of Tween<int> to be
/// appropriate for integers by interpolating between the given begin and end
/// values and then rounding the result to the nearest integer.
class IntTween extends Tween<int> { class IntTween extends Tween<int> {
IntTween({ int begin, int end }) : super(begin: begin, end: end); IntTween({ int begin, int end }) : super(begin: begin, end: end);
...@@ -108,9 +120,15 @@ class IntTween extends Tween<int> { ...@@ -108,9 +120,15 @@ class IntTween extends Tween<int> {
int lerp(double t) => (begin + (end - begin) * t).round(); int lerp(double t) => (begin + (end - begin) * t).round();
} }
/// Transforms the value of the given animation by the given curve.
///
/// This class differs from [CurvedAnimation] in that [CurvedAnimation] applies
/// a curve to an existing [Animation] object whereas [CurveTween] can be
/// chained with another [Tween] prior to receiving the underlying [Animation].
class CurveTween extends Animatable<double> { class CurveTween extends Animatable<double> {
CurveTween({ this.curve }); CurveTween({ this.curve });
/// The curve to use when transforming the value of the animation.
Curve curve; Curve curve;
double evaluate(Animation<double> animation) { double evaluate(Animation<double> animation) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment