Merge pull request #1413 from Hixie/performance
Simplify AnimationPerformance
This commit is contained in:
commit
1d0573fdf2
@ -43,7 +43,7 @@ abstract class WatchableAnimationPerformance {
|
|||||||
void removeStatusListener(AnimationPerformanceStatusListener listener);
|
void removeStatusListener(AnimationPerformanceStatusListener listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of values that animated based on a timeline
|
/// A timeline that can be reversed and used to update [AnimatedVariable]s.
|
||||||
///
|
///
|
||||||
/// For example, a performance may handle an animation of a menu opening by
|
/// 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
|
/// sliding and fading in (changing Y value and opacity) over .5 seconds. The
|
||||||
@ -52,9 +52,10 @@ abstract class WatchableAnimationPerformance {
|
|||||||
/// [fling] the timeline causing a physics-based simulation to take over the
|
/// [fling] the timeline causing a physics-based simulation to take over the
|
||||||
/// progression.
|
/// progression.
|
||||||
class AnimationPerformance implements WatchableAnimationPerformance {
|
class AnimationPerformance implements WatchableAnimationPerformance {
|
||||||
AnimationPerformance({ AnimatedVariable variable, this.duration }) :
|
AnimationPerformance({ this.duration, double progress }) {
|
||||||
_variable = variable {
|
|
||||||
_timeline = new Timeline(_tick);
|
_timeline = new Timeline(_tick);
|
||||||
|
if (progress != null)
|
||||||
|
_timeline.value = progress.clamp(0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a [WatchableAnimationPerformance] for this performance,
|
/// Returns a [WatchableAnimationPerformance] for this performance,
|
||||||
@ -65,18 +66,14 @@ class AnimationPerformance implements WatchableAnimationPerformance {
|
|||||||
/// The length of time this performance should last
|
/// The length of time this performance should last
|
||||||
Duration duration;
|
Duration duration;
|
||||||
|
|
||||||
/// The variable being updated by this performance
|
|
||||||
AnimatedVariable get variable => _variable;
|
|
||||||
void set variable(AnimatedVariable variable) { _variable = variable; }
|
|
||||||
AnimatedVariable _variable;
|
|
||||||
|
|
||||||
Timeline _timeline;
|
Timeline _timeline;
|
||||||
Direction _direction;
|
Direction _direction;
|
||||||
|
|
||||||
/// The direction used to select the current curve
|
/// The direction used to select the current curve
|
||||||
///
|
///
|
||||||
/// Curve direction is only reset when we hit the beginning or the end of the
|
/// 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.
|
/// timeline to avoid discontinuities in the value of any variables this
|
||||||
|
/// performance is used to animate.
|
||||||
Direction _curveDirection;
|
Direction _curveDirection;
|
||||||
|
|
||||||
/// If non-null, animate with this timing instead of a linear timing
|
/// If non-null, animate with this timing instead of a linear timing
|
||||||
@ -85,21 +82,6 @@ class AnimationPerformance implements WatchableAnimationPerformance {
|
|||||||
/// If non-null, animate with this force instead of a zero-to-one timeline.
|
/// If non-null, animate with this force instead of a zero-to-one timeline.
|
||||||
Force attachedForce;
|
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;
|
|
||||||
} else if (variable is AnimatedList) {
|
|
||||||
final AnimatedList variable = this.variable; // TODO(ianh): Remove this line when the analyzer is cleverer
|
|
||||||
variable.variables.add(newVariable);
|
|
||||||
} else {
|
|
||||||
variable = new AnimatedList([variable, newVariable]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The progress of this performance along the timeline
|
/// The progress of this performance along the timeline
|
||||||
///
|
///
|
||||||
/// Note: Setting this value stops the current animation.
|
/// Note: Setting this value stops the current animation.
|
||||||
@ -238,8 +220,10 @@ class AnimationPerformance implements WatchableAnimationPerformance {
|
|||||||
|
|
||||||
void _tick(double t) {
|
void _tick(double t) {
|
||||||
_updateCurveDirection();
|
_updateCurveDirection();
|
||||||
if (variable != null)
|
didTick(t);
|
||||||
variable.setProgress(_curvedProgress, _curveDirection);
|
}
|
||||||
|
|
||||||
|
void didTick(double t) {
|
||||||
_notifyListeners();
|
_notifyListeners();
|
||||||
_checkStatusChanged();
|
_checkStatusChanged();
|
||||||
}
|
}
|
||||||
@ -247,11 +231,15 @@ class AnimationPerformance implements WatchableAnimationPerformance {
|
|||||||
|
|
||||||
/// An animation performance with an animated variable with a concrete type
|
/// An animation performance with an animated variable with a concrete type
|
||||||
class ValueAnimation<T> extends AnimationPerformance {
|
class ValueAnimation<T> extends AnimationPerformance {
|
||||||
ValueAnimation({ AnimatedValue<T> variable, Duration duration }) :
|
ValueAnimation({ this.variable, Duration duration, double progress }) :
|
||||||
super(variable: variable, duration: duration);
|
super(duration: duration, progress: progress);
|
||||||
|
|
||||||
AnimatedValue<T> get variable => _variable as AnimatedValue<T>;
|
|
||||||
void set variable(AnimatedValue<T> v) { _variable = v; }
|
|
||||||
|
|
||||||
|
AnimatedValue<T> variable;
|
||||||
T get value => variable.value;
|
T get value => variable.value;
|
||||||
|
|
||||||
|
void didTick(double t) {
|
||||||
|
if (variable != null)
|
||||||
|
variable.setProgress(_curvedProgress, _curveDirection);
|
||||||
|
super.didTick(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ class _RenderCheckbox extends RenderToggleable {
|
|||||||
..color = uncheckedColor;
|
..color = uncheckedColor;
|
||||||
|
|
||||||
// The rrect contracts slightly during the animation
|
// The rrect contracts slightly during the animation
|
||||||
double inset = 2.0 - (position.value - _kMidpoint).abs() * 2.0;
|
double inset = 2.0 - (position - _kMidpoint).abs() * 2.0;
|
||||||
sky.Rect rect = new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset,
|
sky.Rect rect = new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset,
|
||||||
_kEdgeSize - inset, _kEdgeSize - inset);
|
_kEdgeSize - inset, _kEdgeSize - inset);
|
||||||
sky.RRect rrect = new sky.RRect()
|
sky.RRect rrect = new sky.RRect()
|
||||||
@ -142,19 +142,19 @@ class _RenderCheckbox extends RenderToggleable {
|
|||||||
canvas.drawRRect(rrect, paint);
|
canvas.drawRRect(rrect, paint);
|
||||||
|
|
||||||
// Radial gradient that changes size
|
// Radial gradient that changes size
|
||||||
if (position.value > 0) {
|
if (position > 0) {
|
||||||
paint.setStyle(sky.PaintingStyle.fill);
|
paint.setStyle(sky.PaintingStyle.fill);
|
||||||
paint.setShader(new sky.Gradient.radial(
|
paint.setShader(new sky.Gradient.radial(
|
||||||
new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0),
|
new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0),
|
||||||
_kEdgeSize * (_kMidpoint - position.value) * 8.0, [
|
_kEdgeSize * (_kMidpoint - position) * 8.0, [
|
||||||
const sky.Color(0x00000000),
|
const sky.Color(0x00000000),
|
||||||
uncheckedColor
|
uncheckedColor
|
||||||
]));
|
]));
|
||||||
canvas.drawRRect(rrect, paint);
|
canvas.drawRRect(rrect, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position.value > _kMidpoint) {
|
if (position > _kMidpoint) {
|
||||||
double t = (position.value - _kMidpoint) / (1.0 - _kMidpoint);
|
double t = (position - _kMidpoint) / (1.0 - _kMidpoint);
|
||||||
|
|
||||||
// Solid filled rrect
|
// Solid filled rrect
|
||||||
paint.setStyle(sky.PaintingStyle.strokeAndFill);
|
paint.setStyle(sky.PaintingStyle.strokeAndFill);
|
||||||
|
@ -30,11 +30,11 @@ class InkSplash {
|
|||||||
_radius = new AnimatedValue<double>(
|
_radius = new AnimatedValue<double>(
|
||||||
_kSplashInitialSize, end: _targetRadius, curve: easeOut);
|
_kSplashInitialSize, end: _targetRadius, curve: easeOut);
|
||||||
|
|
||||||
_performance = new AnimationPerformance()
|
_performance = new ValueAnimation<double>(
|
||||||
..variable = _radius
|
variable: _radius,
|
||||||
..duration = new Duration(milliseconds: (_targetRadius / _kSplashUnconfirmedVelocity).floor())
|
duration: new Duration(milliseconds: (_targetRadius / _kSplashUnconfirmedVelocity).floor())
|
||||||
..addListener(_handleRadiusChange)
|
)..addListener(_handleRadiusChange)
|
||||||
..play();
|
..play();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int pointer;
|
final int pointer;
|
||||||
|
@ -35,11 +35,15 @@ abstract class ProgressIndicator extends StatefulComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProgressIndicatorState extends State<ProgressIndicator> {
|
class ProgressIndicatorState extends State<ProgressIndicator> {
|
||||||
|
|
||||||
|
ValueAnimation<double> _performance;
|
||||||
|
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_performance = new AnimationPerformance()
|
_performance = new ValueAnimation<double>(
|
||||||
..duration = const Duration(milliseconds: 1500)
|
variable: new AnimatedValue<double>(0.0, end: 1.0, curve: ease),
|
||||||
..variable = new AnimatedValue<double>(0.0, end: 1.0, curve: ease);
|
duration: const Duration(milliseconds: 1500)
|
||||||
|
);
|
||||||
_performance.addStatusListener((AnimationStatus status) {
|
_performance.addStatusListener((AnimationStatus status) {
|
||||||
if (status == AnimationStatus.completed)
|
if (status == AnimationStatus.completed)
|
||||||
_restartAnimation();
|
_restartAnimation();
|
||||||
@ -47,9 +51,6 @@ class ProgressIndicatorState extends State<ProgressIndicator> {
|
|||||||
_performance.play();
|
_performance.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationPerformance _performance;
|
|
||||||
double get _performanceValue => (_performance.variable as AnimatedValue<double>).value;
|
|
||||||
|
|
||||||
void _restartAnimation() {
|
void _restartAnimation() {
|
||||||
_performance.progress = 0.0;
|
_performance.progress = 0.0;
|
||||||
_performance.play();
|
_performance.play();
|
||||||
@ -57,13 +58,13 @@ class ProgressIndicatorState extends State<ProgressIndicator> {
|
|||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (config.value != null)
|
if (config.value != null)
|
||||||
return config._buildIndicator(context, _performanceValue);
|
return config._buildIndicator(context, _performance.value);
|
||||||
|
|
||||||
return new BuilderTransition(
|
return new BuilderTransition(
|
||||||
variables: [_performance.variable],
|
variables: [_performance.variable],
|
||||||
performance: _performance.view,
|
performance: _performance.view,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return config._buildIndicator(context, _performanceValue);
|
return config._buildIndicator(context, _performance.value);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -97,9 +97,9 @@ class _RenderSwitch extends RenderToggleable {
|
|||||||
_radialReaction = new RadialReaction(
|
_radialReaction = new RadialReaction(
|
||||||
center: new Point(_kSwitchSize.width / 2.0, _kSwitchSize.height / 2.0),
|
center: new Point(_kSwitchSize.width / 2.0, _kSwitchSize.height / 2.0),
|
||||||
radius: _kReactionRadius,
|
radius: _kReactionRadius,
|
||||||
startPosition: startLocation)
|
startPosition: startLocation
|
||||||
..addListener(markNeedsPaint)
|
)..addListener(markNeedsPaint)
|
||||||
..show();
|
..show();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _hideRadialReaction() async {
|
Future _hideRadialReaction() async {
|
||||||
@ -140,10 +140,10 @@ class _RenderSwitch extends RenderToggleable {
|
|||||||
paint.drawLooper = builder.build();
|
paint.drawLooper = builder.build();
|
||||||
|
|
||||||
// The thumb contracts slightly during the animation
|
// The thumb contracts slightly during the animation
|
||||||
double inset = 2.0 - (position.value - 0.5).abs() * 2.0;
|
double inset = 2.0 - (position - 0.5).abs() * 2.0;
|
||||||
Point thumbPos = new Point(offset.dx +
|
Point thumbPos = new Point(offset.dx +
|
||||||
_kTrackRadius +
|
_kTrackRadius +
|
||||||
position.value * (_kTrackWidth - _kTrackRadius * 2),
|
position * (_kTrackWidth - _kTrackRadius * 2),
|
||||||
offset.dy + _kSwitchHeight / 2.0);
|
offset.dy + _kSwitchHeight / 2.0);
|
||||||
canvas.drawCircle(thumbPos, _kThumbRadius - inset, paint);
|
canvas.drawCircle(thumbPos, _kThumbRadius - inset, paint);
|
||||||
}
|
}
|
||||||
|
@ -30,16 +30,16 @@ class RadialReaction {
|
|||||||
_outerOpacity = new AnimatedValue<double>(0.0, end: _kMaxOpacity, curve: easeOut);
|
_outerOpacity = new AnimatedValue<double>(0.0, end: _kMaxOpacity, curve: easeOut);
|
||||||
_innerCenter = new AnimatedValue<Point>(startPosition, end: center, curve: easeOut);
|
_innerCenter = new AnimatedValue<Point>(startPosition, end: center, curve: easeOut);
|
||||||
_innerRadius = new AnimatedValue<double>(0.0, end: radius, curve: easeOut);
|
_innerRadius = new AnimatedValue<double>(0.0, end: radius, curve: easeOut);
|
||||||
_showPerformance = new AnimationPerformance()
|
_showPerformance = new AnimationPerformance(duration: _kShowDuration)
|
||||||
..addVariable(_outerOpacity)
|
..addListener(() {
|
||||||
..addVariable(_innerCenter)
|
_showPerformance.updateVariable(_outerOpacity);
|
||||||
..addVariable(_innerRadius)
|
_showPerformance.updateVariable(_innerCenter);
|
||||||
..duration = _kShowDuration;
|
_showPerformance.updateVariable(_innerRadius);
|
||||||
|
});
|
||||||
_fade = new AnimatedValue(1.0, end: 0.0, curve: easeIn);
|
_fade = new ValueAnimation<double>(
|
||||||
_hidePerformance = new AnimationPerformance()
|
variable: new AnimatedValue(1.0, end: 0.0, curve: easeIn),
|
||||||
..addVariable(_fade)
|
duration: _kHideDuration
|
||||||
..duration =_kHideDuration;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The center of the circle in which the reaction occurs
|
/// The center of the circle in which the reaction occurs
|
||||||
@ -55,8 +55,7 @@ class RadialReaction {
|
|||||||
|
|
||||||
Future _showComplete;
|
Future _showComplete;
|
||||||
|
|
||||||
AnimationPerformance _hidePerformance;
|
ValueAnimation<double> _fade;
|
||||||
AnimatedValue<double> _fade;
|
|
||||||
|
|
||||||
/// Show the reaction
|
/// Show the reaction
|
||||||
///
|
///
|
||||||
@ -70,13 +69,13 @@ class RadialReaction {
|
|||||||
/// Returns a future that resolves when the reaction is completely hidden.
|
/// Returns a future that resolves when the reaction is completely hidden.
|
||||||
Future hide() async {
|
Future hide() async {
|
||||||
await _showComplete;
|
await _showComplete;
|
||||||
await _hidePerformance.forward();
|
await _fade.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call listener whenever the visual appearance of the reaction changes
|
/// Call listener whenever the visual appearance of the reaction changes
|
||||||
void addListener(Function listener) {
|
void addListener(Function listener) {
|
||||||
_showPerformance.addListener(listener);
|
_showPerformance.addListener(listener);
|
||||||
_hidePerformance.addListener(listener);
|
_fade.addListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Paint _outerPaint = new Paint();
|
final Paint _outerPaint = new Paint();
|
||||||
|
@ -24,13 +24,18 @@ abstract class RenderToggleable extends RenderConstrainedBox {
|
|||||||
: _value = value,
|
: _value = value,
|
||||||
_onChanged = onChanged,
|
_onChanged = onChanged,
|
||||||
super(additionalConstraints: new BoxConstraints.tight(size)) {
|
super(additionalConstraints: new BoxConstraints.tight(size)) {
|
||||||
_performance = new AnimationPerformance()
|
_performance = new ValueAnimation<double>(
|
||||||
..variable = _position
|
variable: new AnimatedValue<double>(0.0, end: 1.0, curve: easeIn, reverseCurve: easeOut),
|
||||||
..duration = _kToggleDuration
|
duration: _kToggleDuration,
|
||||||
..progress = _value ? 1.0 : 0.0
|
progress: _value ? 1.0 : 0.0
|
||||||
..addListener(markNeedsPaint);
|
)..addListener(markNeedsPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueAnimation<double> get performance => _performance;
|
||||||
|
ValueAnimation<double> _performance;
|
||||||
|
|
||||||
|
double get position => _performance.value;
|
||||||
|
|
||||||
void handleEvent(sky.Event event, BoxHitTestEntry entry) {
|
void handleEvent(sky.Event event, BoxHitTestEntry entry) {
|
||||||
if (event.type == 'pointerdown')
|
if (event.type == 'pointerdown')
|
||||||
_tap.addPointer(event);
|
_tap.addPointer(event);
|
||||||
@ -68,15 +73,7 @@ abstract class RenderToggleable extends RenderConstrainedBox {
|
|||||||
|
|
||||||
ValueChanged get onChanged => _onChanged;
|
ValueChanged get onChanged => _onChanged;
|
||||||
ValueChanged _onChanged;
|
ValueChanged _onChanged;
|
||||||
|
|
||||||
void set onChanged(ValueChanged onChanged) {
|
void set onChanged(ValueChanged onChanged) {
|
||||||
_onChanged = onChanged;
|
_onChanged = onChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatedValue<double> get position => _position;
|
|
||||||
final AnimatedValue<double> _position =
|
|
||||||
new AnimatedValue<double>(0.0, end: 1.0, curve: easeIn, reverseCurve: easeOut);
|
|
||||||
|
|
||||||
AnimationPerformance get performance => _performance;
|
|
||||||
AnimationPerformance _performance;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user