From 5a3f62b2c56f5b3b6dfadc4a9308af481e111e1c Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 8 Sep 2015 13:22:54 -0700 Subject: [PATCH] Add dartdoc for the animation library --- .../src/animation/animated_simulation.dart | 25 +++- .../sky/lib/src/animation/animated_value.dart | 45 ++++++- .../src/animation/animation_performance.dart | 120 ++++++++++++------ .../sky/lib/src/animation/curves.dart | 39 ++++++ .../sky/lib/src/animation/forces.dart | 18 ++- .../lib/src/animation/scroll_behavior.dart | 31 ++++- .../sky/lib/src/animation/timeline.dart | 25 ++-- 7 files changed, 236 insertions(+), 67 deletions(-) diff --git a/sky/packages/sky/lib/src/animation/animated_simulation.dart b/sky/packages/sky/lib/src/animation/animated_simulation.dart index 18ce06fc88e..0710dfc6d25 100644 --- a/sky/packages/sky/lib/src/animation/animated_simulation.dart +++ b/sky/packages/sky/lib/src/animation/animated_simulation.dart @@ -9,14 +9,22 @@ import 'package:sky/src/animation/scheduler.dart'; const double _kSecondsPerMillisecond = 1000.0; -class Ticker { - Ticker(Function onTick) : _onTick = onTick; +// TODO(abarth): Change from double to Duration. +typedef _TickerCallback(double timeStamp); - final Function _onTick; +/// Calls its callback once per animation frame +class Ticker { + /// Constructs a ticker that will call onTick once per frame while running + Ticker(_TickerCallback onTick) : _onTick = onTick; + + final _TickerCallback _onTick; Completer _completer; int _animationId; + /// Start calling onTick once per animation frame + /// + /// The returned future resolves once the ticker stops ticking. Future start() { assert(!isTicking); _completer = new Completer(); @@ -24,6 +32,9 @@ class Ticker { return _completer.future; } + /// Stop calling onTick + /// + /// Causes the future returned by [start] to resolve. void stop() { if (!isTicking) return; @@ -42,6 +53,7 @@ class Ticker { localCompleter.complete(); } + /// Whether this ticker has scheduled a call to onTick bool get isTicking => _completer != null; void _tick(double timeStamp) { @@ -63,6 +75,7 @@ class Ticker { } } +/// Ticks a simulation once per frame class AnimatedSimulation { AnimatedSimulation(Function onTick) : _onTick = onTick { @@ -76,6 +89,7 @@ class AnimatedSimulation { double _startTime; double _value = 0.0; + /// The current value of the simulation double get value => _value; void set value(double newValue) { assert(!_ticker.isTicking); @@ -83,6 +97,9 @@ class AnimatedSimulation { _onTick(_value); } + /// Start ticking the given simulation once per frame + /// + /// Returns a future that resolves when the simulation stops ticking. Future start(Simulation simulation) { assert(simulation != null); assert(!_ticker.isTicking); @@ -92,12 +109,14 @@ class AnimatedSimulation { return _ticker.start(); } + /// Stop ticking the current simulation void stop() { _simulation = null; _startTime = null; _ticker.stop(); } + /// Whether this object is currently ticking a simulation bool get isAnimating => _ticker.isTicking; void _tick(double timeStamp) { diff --git a/sky/packages/sky/lib/src/animation/animated_value.dart b/sky/packages/sky/lib/src/animation/animated_value.dart index 7f9877d911c..8c64fdde6e3 100644 --- a/sky/packages/sky/lib/src/animation/animated_value.dart +++ b/sky/packages/sky/lib/src/animation/animated_value.dart @@ -6,24 +6,48 @@ import "dart:sky"; import 'package:sky/src/animation/curves.dart'; +/// The direction in which an animation is running enum Direction { + /// The animation is running from beginning to end forward, + + /// The animation is running backwards, from end to beginning reverse } +/// A variable that changes as an animation progresses abstract class AnimatedVariable { + /// Update the variable to a given time in an animation that is running in the given direction void setProgress(double t, Direction direction); String toString(); } +/// class AnimationTiming { - AnimationTiming({this.interval, this.reverseInterval, this.curve, this.reverseCurve}); + AnimationTiming({ + this.interval, + this.reverseInterval, + this.curve, + this.reverseCurve + }); + /// The interval during which this timing is active in the forward direction Interval interval; + + /// The interval during which this timing is active in the reverse direction + /// + /// If this field is null, the timing defaules to using [interval] in both directions. Interval reverseInterval; + + /// The curve that this timing applies to the animation clock in the forward direction Curve curve; + + /// The curve that this timing applies to the animation clock in the reverse direction + /// + /// If this field is null, the timing defaules to using [curve] in both directions. Curve reverseCurve; + /// Applies this timing to the given animation clock value in the given direction double transform(double t, Direction direction) { Interval interval = _getInterval(direction); if (interval != null) @@ -49,18 +73,26 @@ class AnimationTiming { } } +/// An animated variable with a concrete type class AnimatedValue extends AnimationTiming implements AnimatedVariable { AnimatedValue(this.begin, { this.end, Interval interval, Curve curve, Curve reverseCurve }) : super(interval: interval, curve: curve, reverseCurve: 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; + /// Updates the value of this variable according to the given animation clock value and direction void setProgress(double t, Direction direction) { if (end != null) { t = transform(t, direction); @@ -71,12 +103,15 @@ class AnimatedValue extends AnimationTiming implements Animat String toString() => 'AnimatedValue(begin=$begin, end=$end, value=$value)'; } +/// A list of animated variables class AnimatedList extends AnimationTiming implements AnimatedVariable { + /// The list of variables contained in the list List variables; AnimatedList(this.variables, { Interval interval, Curve curve, Curve reverseCurve }) : super(interval: interval, curve: curve, reverseCurve: reverseCurve); + // Updates the value of all the variables in the list according to the given animation clock value and direction void setProgress(double t, Direction direction) { double adjustedTime = transform(t, direction); for (AnimatedVariable variable in variables) @@ -86,6 +121,10 @@ class AnimatedList extends AnimationTiming implements AnimatedVariable { String toString() => 'AnimatedList([$variables])'; } +/// An animated variable containing a color +/// +/// This class specializes the interpolation of AnimatedValue to be +/// appropriate for colors. class AnimatedColorValue extends AnimatedValue { AnimatedColorValue(Color begin, { Color end, Curve curve }) : super(begin, end: end, curve: curve); @@ -93,6 +132,10 @@ class AnimatedColorValue extends AnimatedValue { Color lerp(double t) => Color.lerp(begin, end, t); } +/// An animated variable containing a rectangle +/// +/// This class specializes the interpolation of AnimatedValue to be +/// appropriate for rectangles. class AnimatedRect extends AnimatedValue { AnimatedRect(Rect begin, { Rect end, Curve curve }) : super(begin, end: end, curve: curve); diff --git a/sky/packages/sky/lib/src/animation/animation_performance.dart b/sky/packages/sky/lib/src/animation/animation_performance.dart index af0c1744590..92046edd4b2 100644 --- a/sky/packages/sky/lib/src/animation/animation_performance.dart +++ b/sky/packages/sky/lib/src/animation/animation_performance.dart @@ -8,50 +8,62 @@ import 'package:sky/src/animation/animated_value.dart'; import 'package:sky/src/animation/forces.dart'; import 'package:sky/src/animation/timeline.dart'; +/// The status of an animation enum AnimationStatus { - dismissed, // stoped at 0 - forward, // animating from 0 => 1 - reverse, // animating from 1 => 0 - completed, // stopped at 1 + /// The animation is stopped at the beginning + dismissed, + + /// The animation is running from beginning to end + forward, + + /// The animation is running backwards, from end to beginning + reverse, + + /// The animation is stopped at the end + completed, } -// This class manages a "performance" - a collection of values that change -// based on a timeline. For example, a performance may handle an animation -// of a menu opening by sliding and fading in (changing Y value and opacity) -// over .5 seconds. The performance can move forwards (present) or backwards -// (dismiss). A consumer may also take direct control of the timeline by -// manipulating |progress|, or |fling| the timeline causing a physics-based -// simulation to take over the progression. +/// A collection of values that animated based on a timeline +/// +/// For example, a performance may handle an animation of a menu opening by +/// sliding and fading in (changing Y value and opacity) over .5 seconds. The +/// performance can move forwards (present) or backwards (dismiss). A consumer +/// may also take direct control of the timeline by manipulating [progress], or +/// [fling] the timeline causing a physics-based simulation to take over the +/// progression. class AnimationPerformance { AnimationPerformance({AnimatedVariable variable, this.duration}) : _variable = variable { _timeline = new Timeline(_tick); } - AnimatedVariable _variable; + /// The length of time this performance should last Duration duration; + /// The variable being updated by this performance AnimatedVariable get variable => _variable; - void set variable(AnimatedVariable v) { _variable = v; } + void set variable(AnimatedVariable variable) { _variable = variable; } + AnimatedVariable _variable; - // Advances from 0 to 1. On each tick, we'll update our variable's values. Timeline _timeline; - Timeline get timeline => _timeline; - Direction _direction; - Direction get direction => _direction; - // This controls which curve we use for variables with different curves in - // the forward/reverse directions. Curve direction is only reset when we hit - // 0 or 1, to avoid discontinuities. + /// The direction used to select the current curve + /// + /// Curve direction is only reset when we hit the beginning or the end of the + /// timeline to avoid discontinuities in the value of the variable. Direction _curveDirection; - Direction get curveDirection => _curveDirection; + /// If non-null, animate with this timing instead of a linear timing AnimationTiming timing; - // If non-null, animate with this force instead of a tween animation. + /// If non-null, animate with this force instead of a zero-to-one timeline. Force attachedForce; + /// Add a variable to this animation + /// + /// If there are no attached variables, this variable becomes the value of + /// [variable]. Otherwise, all the variables are stored in an [AnimatedList]. void addVariable(AnimatedVariable newVariable) { if (variable == null) { variable = newVariable; @@ -62,70 +74,92 @@ class AnimationPerformance { } } - double get progress => timeline.value; + /// The progress of this performance along the timeline + /// + /// Note: Setting this value stops the current animation. + double get progress => _timeline.value; void set progress(double t) { // TODO(mpcomplete): should this affect |direction|? stop(); - timeline.value = t.clamp(0.0, 1.0); + _timeline.value = t.clamp(0.0, 1.0); _checkStatusChanged(); } - double get curvedProgress { - return timing != null ? timing.transform(progress, curveDirection) : progress; + double get _curvedProgress { + return timing != null ? timing.transform(progress, _curveDirection) : progress; } + /// Whether this animation is stopped at the beginning bool get isDismissed => status == AnimationStatus.dismissed; - bool get isCompleted => status == AnimationStatus.completed; - bool get isAnimating => timeline.isAnimating; + /// Whether this animation is stopped at the end + bool get isCompleted => status == AnimationStatus.completed; + + /// Whether this animation is currently animating in either the forward or reverse direction + bool get isAnimating => _timeline.isAnimating; + + /// The current status of this animation AnimationStatus get status { if (!isAnimating && progress == 1.0) return AnimationStatus.completed; if (!isAnimating && progress == 0.0) return AnimationStatus.dismissed; - return direction == Direction.forward ? + return _direction == Direction.forward ? AnimationStatus.forward : AnimationStatus.reverse; } + /// Update the given varaible according to the current progress of this performance void updateVariable(AnimatedVariable variable) { - variable.setProgress(curvedProgress, curveDirection); + variable.setProgress(_curvedProgress, _curveDirection); } + /// Start running this animation in the given direction Future play([Direction direction = Direction.forward]) { _direction = direction; return resume(); } + + /// Start running this animation forwards (towards the end) Future forward() => play(Direction.forward); + + /// Start running this animation in reverse (towards the beginning) Future reverse() => play(Direction.reverse); + + /// Start running this animation in the most recently direction Future resume() { if (attachedForce != null) { return fling(velocity: _direction == Direction.forward ? 1.0 : -1.0, force: attachedForce); } - return _animateTo(direction == Direction.forward ? 1.0 : 0.0); + return _animateTo(_direction == Direction.forward ? 1.0 : 0.0); } + /// Stop running this animation void stop() { - timeline.stop(); + _timeline.stop(); } - // Flings the timeline with an optional force (defaults to a critically - // damped spring) and initial velocity. If velocity is positive, the - // animation will complete, otherwise it will dismiss. + /// Start running this animation according to the given physical parameters + /// + /// Flings the timeline with an optional force (defaults to a critically + /// damped spring) and initial velocity. If velocity is positive, the + /// animation will complete, otherwise it will dismiss. Future fling({double velocity: 1.0, Force force}) { if (force == null) force = kDefaultSpringForce; _direction = velocity < 0.0 ? Direction.reverse : Direction.forward; - return timeline.fling(force.release(progress, velocity)); + return _timeline.fling(force.release(progress, velocity)); } final List _listeners = new List(); + /// Calls the listener every time the progress of this performance changes void addListener(Function listener) { _listeners.add(listener); } + /// Stop calling the listener every time the progress of this performance changes void removeListener(Function listener) { _listeners.remove(listener); } @@ -138,10 +172,12 @@ class AnimationPerformance { final List _statusListeners = new List(); + /// Calls listener every time the status of this performance changes void addStatusListener(Function listener) { _statusListeners.add(listener); } + /// Stops calling the listener every time the status of this performance changes void removeStatusListener(Function listener) { _statusListeners.remove(listener); } @@ -160,28 +196,28 @@ class AnimationPerformance { void _updateCurveDirection() { if (status != _lastStatus) { if (_lastStatus == AnimationStatus.dismissed || _lastStatus == AnimationStatus.completed) - _curveDirection = direction; + _curveDirection = _direction; } } Future _animateTo(double target) { - Duration remainingDuration = duration * (target - timeline.value).abs(); - timeline.stop(); + Duration remainingDuration = duration * (target - _timeline.value).abs(); + _timeline.stop(); if (remainingDuration == Duration.ZERO) return new Future.value(); - return timeline.animateTo(target, duration: remainingDuration); + return _timeline.animateTo(target, duration: remainingDuration); } void _tick(double t) { _updateCurveDirection(); if (variable != null) - variable.setProgress(curvedProgress, curveDirection); + variable.setProgress(_curvedProgress, _curveDirection); _notifyListeners(); _checkStatusChanged(); } } -// Simple helper class for an animation with a single value. +/// An animation performance with an animated variable with a concrete type class ValueAnimation extends AnimationPerformance { ValueAnimation({AnimatedValue variable, Duration duration}) : super(variable: variable, duration: duration); diff --git a/sky/packages/sky/lib/src/animation/curves.dart b/sky/packages/sky/lib/src/animation/curves.dart index 5e9cb6892e1..d7dd325efdb 100644 --- a/sky/packages/sky/lib/src/animation/curves.dart +++ b/sky/packages/sky/lib/src/animation/curves.dart @@ -11,10 +11,17 @@ double _evaluateCubic(double a, double b, double m) { const double _kCubicErrorBound = 0.001; +/// A mapping of the unit interval to the unit interval +/// +/// A curve must map 0.0 to 0.0 and 1.0 to 1.0. abstract class Curve { + /// Return the value of the curve at point t + /// + /// The value of t must be between 0.0 and 1.0, inclusive. double transform(double t); } +/// The idenity map over the unit interval class Linear implements Curve { const Linear(); @@ -23,8 +30,12 @@ class Linear implements Curve { } } +/// A curve that is initially 0.0, then linear, then 1.0 class Interval implements Curve { + /// The smallest value for which this interval is 0.0 final double start; + + /// The smallest value for which this interval is 1.0 final double end; Interval(this.start, this.end) { @@ -39,6 +50,7 @@ class Interval implements Curve { } } +/// A cubic polynomial mapping of the unit interval class Cubic implements Curve { final double a; final double b; @@ -79,6 +91,7 @@ double _bounce(double t) { return 7.5625 * t * t + 0.984375; } +/// An oscillating curve that grows in magnitude class BounceInCurve implements Curve { const BounceInCurve(); @@ -87,6 +100,7 @@ class BounceInCurve implements Curve { } } +/// An oscillating curve that shrink in magnitude class BounceOutCurve implements Curve { const BounceOutCurve(); @@ -95,6 +109,7 @@ class BounceOutCurve implements Curve { } } +/// An oscillating curve that first grows and then shrink in magnitude class BounceInOutCurve implements Curve { const BounceInOutCurve(); @@ -106,6 +121,7 @@ class BounceInOutCurve implements Curve { } } +/// An oscillating curve that grows in magnitude while overshootings its bounds class ElasticInCurve implements Curve { const ElasticInCurve([this.period = 0.4]); final double period; @@ -117,6 +133,7 @@ class ElasticInCurve implements Curve { } } +/// An oscillating curve that shrinks in magnitude while overshootings its bounds class ElasticOutCurve implements Curve { const ElasticOutCurve([this.period = 0.4]); final double period; @@ -127,6 +144,7 @@ class ElasticOutCurve implements Curve { } } +/// An oscillating curve that grows and then shrinks in magnitude while overshootings its bounds class ElasticInOutCurve implements Curve { const ElasticInOutCurve([this.period = 0.4]); final double period; @@ -141,14 +159,35 @@ class ElasticInOutCurve implements Curve { } } +/// A linear animation curve const Linear linear = const Linear(); + +/// A cubic animation cuve that speeds up quickly and ends slowly const Cubic ease = const Cubic(0.25, 0.1, 0.25, 1.0); + +/// A cubic animation cuve that starts slowly and ends quickly const Cubic easeIn = const Cubic(0.42, 0.0, 1.0, 1.0); + +/// A cubic animation cuve that starts quickly and ends slowly const Cubic easeOut = const Cubic(0.0, 0.0, 0.58, 1.0); + +/// A cubic animation cuve that starts slowly, speeds up, and then and ends slowly const Cubic easeInOut = const Cubic(0.42, 0.0, 0.58, 1.0); + +/// An oscillating curve that grows in magnitude const BounceInCurve bounceIn = const BounceInCurve(); + +/// An oscillating curve that first grows and then shrink in magnitude const BounceOutCurve bounceOut = const BounceOutCurve(); + +/// An oscillating curve that first grows and then shrink in magnitude const BounceInOutCurve bounceInOut = const BounceInOutCurve(); + +/// An oscillating curve that grows in magnitude while overshootings its bounds const ElasticInCurve elasticIn = const ElasticInCurve(); + +/// An oscillating curve that shrinks in magnitude while overshootings its bounds const ElasticOutCurve elasticOut = const ElasticOutCurve(); + +/// An oscillating curve that grows and then shrinks in magnitude while overshootings its bounds const ElasticInOutCurve elasticInOut = const ElasticInOutCurve(); diff --git a/sky/packages/sky/lib/src/animation/forces.dart b/sky/packages/sky/lib/src/animation/forces.dart index 8c57978015f..47cef10d810 100644 --- a/sky/packages/sky/lib/src/animation/forces.dart +++ b/sky/packages/sky/lib/src/animation/forces.dart @@ -4,26 +4,31 @@ import 'package:newton/newton.dart'; -// Base class for creating Simulations for the animation Timeline. +/// A factory for simulations abstract class Force { const Force(); Simulation release(double position, double velocity); } +/// A factory for spring-based physics simulations class SpringForce extends Force { const SpringForce(this.spring, { this.left: 0.0, this.right: 1.0 }); + /// The description of the spring to be used in the created simulations final SpringDescription spring; - // Where to put the spring's resting point when releasing left or right, - // respectively. + /// Where to put the spring's resting point when releasing left final double left; + + /// Where to put the spring's resting point when releasing right final double right; - // We overshoot the target by this distance, but stop the simulation when - // the spring gets within this distance (regardless of how fast it's moving). - // This causes the spring to settle a bit faster than it otherwise would. + /// How pricely to terminate the simulation + /// + /// We overshoot the target by this distance, but stop the simulation when + /// the spring gets within this distance (regardless of how fast it's moving). + /// This causes the spring to settle a bit faster than it otherwise would. static const Tolerance tolerance = const Tolerance( velocity: double.INFINITY, distance: 0.01 @@ -43,4 +48,5 @@ final SpringDescription _kDefaultSpringDesc = new SpringDescription.withDampingR ratio: 1.0 ); +/// A spring force with reasonable default values final SpringForce kDefaultSpringForce = new SpringForce(_kDefaultSpringDesc); diff --git a/sky/packages/sky/lib/src/animation/scroll_behavior.dart b/sky/packages/sky/lib/src/animation/scroll_behavior.dart index b8660a47ee3..cd209761f4d 100644 --- a/sky/packages/sky/lib/src/animation/scroll_behavior.dart +++ b/sky/packages/sky/lib/src/animation/scroll_behavior.dart @@ -9,24 +9,36 @@ import 'package:newton/newton.dart'; const double _kSecondsPerMillisecond = 1000.0; const double _kScrollDrag = 0.025; +/// An interface for controlling the behavior of scrollable widgets abstract class ScrollBehavior { + /// A simulation to run to determine the scroll offset + /// + /// Called when the user stops scrolling at a given position with a given + /// instantaneous velocity. Simulation release(double position, double velocity) => null; - // Returns the new scroll offset. + /// The new scroll offset to use when the user attempts to scroll from the given offset by the given delta double applyCurve(double scrollOffset, double scrollDelta); } +/// A scroll behavior for a scrollable widget with linear extent abstract class ExtentScrollBehavior extends ScrollBehavior { ExtentScrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 }) : _contentExtent = contentExtent, _containerExtent = containerExtent; - double _contentExtent; + /// The linear extent of the content inside the scrollable widget double get contentExtent => _contentExtent; + double _contentExtent; - double _containerExtent; + /// The linear extent of the exterior of the scrollable widget double get containerExtent => _containerExtent; + double _containerExtent; - /// Returns the new scrollOffset. + /// Update either content or container extent (or both) + /// + /// The scrollOffset parameter is the scroll offset of the widget before the + /// change in extent. Returns the new scroll offset of the widget after the + /// change in extent. double updateExtents({ double contentExtent, double containerExtent, @@ -39,10 +51,14 @@ abstract class ExtentScrollBehavior extends ScrollBehavior { return scrollOffset.clamp(minScrollOffset, maxScrollOffset); } + /// The minimum value the scroll offset can obtain double get minScrollOffset; + + /// The maximum value the scroll offset can obatin double get maxScrollOffset; } +/// A scroll behavior that prevents the user from exeeding scroll bounds class BoundedBehavior extends ExtentScrollBehavior { BoundedBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 }) : super(contentExtent: contentExtent, containerExtent: containerExtent); @@ -55,6 +71,7 @@ class BoundedBehavior extends ExtentScrollBehavior { } } +/// A scroll behavior that does not prevent the user from exeeding scroll bounds class UnboundedBehavior extends ExtentScrollBehavior { UnboundedBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 }) : super(contentExtent: contentExtent, containerExtent: containerExtent); @@ -74,19 +91,20 @@ class UnboundedBehavior extends ExtentScrollBehavior { } } -Simulation createDefaultScrollSimulation(double position, double velocity, double minScrollOffset, double maxScrollOffset) { +Simulation _createDefaultScrollSimulation(double position, double velocity, double minScrollOffset, double maxScrollOffset) { double velocityPerSecond = velocity * _kSecondsPerMillisecond; SpringDescription spring = new SpringDescription.withDampingRatio( mass: 1.0, springConstant: 170.0, ratio: 1.1); return new ScrollSimulation(position, velocityPerSecond, minScrollOffset, maxScrollOffset, spring, _kScrollDrag); } +/// A scroll behavior that lets the user scroll beyond the scroll bounds with some resistance class OverscrollBehavior extends BoundedBehavior { OverscrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 }) : super(contentExtent: contentExtent, containerExtent: containerExtent); Simulation release(double position, double velocity) { - return createDefaultScrollSimulation(position, velocity, minScrollOffset, maxScrollOffset); + return _createDefaultScrollSimulation(position, velocity, minScrollOffset, maxScrollOffset); } double applyCurve(double scrollOffset, double scrollDelta) { @@ -106,6 +124,7 @@ class OverscrollBehavior extends BoundedBehavior { } } +/// A scroll behavior that lets the user scroll beyond the scroll bounds only when the bounds are disjoint class OverscrollWhenScrollableBehavior extends OverscrollBehavior { bool get isScrollable => contentExtent > containerExtent; diff --git a/sky/packages/sky/lib/src/animation/timeline.dart b/sky/packages/sky/lib/src/animation/timeline.dart index 294c918930d..75da47d5f8b 100644 --- a/sky/packages/sky/lib/src/animation/timeline.dart +++ b/sky/packages/sky/lib/src/animation/timeline.dart @@ -8,10 +8,14 @@ import 'package:newton/newton.dart'; import 'package:sky/src/animation/animated_simulation.dart'; -// Simple simulation that linearly varies from |begin| to |end| over |duration|. +/// A simulation that linearly varies from [begin] to [end] over [duration] class TweenSimulation extends Simulation { final double _durationInSeconds; + + /// The initial value of the simulation final double begin; + + /// The terminal value of the simulation final double end; TweenSimulation(Duration duration, this.begin, this.end) : @@ -32,14 +36,15 @@ class TweenSimulation extends Simulation { bool isDone(double timeInSeconds) => timeInSeconds > _durationInSeconds; } +/// A timeline for an animation class Timeline { - Timeline(Function onTick) : _onTick = onTick { - _animation = new AnimatedSimulation(_tick); + Timeline(Function onTick) { + _animation = new AnimatedSimulation(onTick); } - final Function _onTick; AnimatedSimulation _animation; + /// The current value of the timeline double get value => _animation.value.clamp(0.0, 1.0); void set value(double newValue) { assert(newValue != null && newValue >= 0.0 && newValue <= 1.0); @@ -47,6 +52,7 @@ class Timeline { _animation.value = newValue; } + /// Whether the timeline is currently animating bool get isAnimating => _animation.isAnimating; Future _start({ @@ -59,22 +65,23 @@ class Timeline { return _animation.start(new TweenSimulation(duration, begin, end)); } + /// Animate value of the timeline to the given target over the given duration + /// + /// Returns a future that resolves when the timeline stops animating, + /// typically when the timeline arives at the target value. Future animateTo(double target, { Duration duration }) { assert(duration > Duration.ZERO); return _start(duration: duration, begin: value, end: target); } + /// Stop animating the timeline void stop() { _animation.stop(); } - // Give |simulation| control over the timeline. + // Gives the given simulation control over the timeline Future fling(Simulation simulation) { stop(); return _animation.start(simulation); } - - void _tick(double newValue) { - _onTick(value); - } }