Chromium Code Reviews| Index: sky/sdk/lib/widgets/material.dart |
| diff --git a/sky/sdk/lib/widgets/material.dart b/sky/sdk/lib/widgets/material.dart |
| index 864cf1a6af204ac7dd1dba5c20582b17a2492a37..960b16e33d05f7e65e468179781ee3d46fad68f4 100644 |
| --- a/sky/sdk/lib/widgets/material.dart |
| +++ b/sky/sdk/lib/widgets/material.dart |
| @@ -2,28 +2,69 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +import '../animation/animated_value.dart'; |
| import '../painting/box_painter.dart'; |
| import '../theme/colors.dart' as colors; |
| import '../theme/edges.dart'; |
| import '../theme/shadows.dart'; |
| +import 'animated_component.dart'; |
| import 'basic.dart'; |
| import 'default_text_style.dart'; |
| import 'theme.dart'; |
| -class Material extends Component { |
| +const double _kAnimateShadowDurationMS = 100.0; |
| + |
| +// Ugly code to linearly interpolate 2 BoxShadows. |
| +double lerpDouble(double p1, double p2, double t) => p1 * (1.0 - t) + p2 * t; |
| + |
| +Color lerpColor(Color p1, Color p2, double t) => |
| + new Color.fromARGB((p1.alpha * (1.0 - t) + p2.alpha * t).toInt(), |
| + (p1.red * (1.0 - t) + p2.red * t).toInt(), |
| + (p1.green * (1.0 - t) + p2.green * t).toInt(), |
| + (p1.blue * (1.0 - t) + p2.blue * t).toInt()); |
| + |
| +Size lerpSize(Size p1, Size p2, double t) => |
| + new Size(p1.width * (1.0 - t) + p2.width * t, |
| + p1.height * (1.0 - t) + p2.height * t); |
| + |
| +BoxShadow lerpShadow(BoxShadow p1, BoxShadow p2, double t) { |
| + return new BoxShadow( |
| + color: lerpColor(p1.color, p2.color, t), |
| + offset: lerpSize(p1.offset, p2.offset, t), |
| + blur: lerpDouble(p1.blur, p2.blur, t)); |
| +} |
| + |
| +List<BoxShadow> computeShadow(double level) { |
| + if (level < 1.0) // shadows[1] is the first shadow |
|
Hixie
2015/06/25 22:42:19
Can't we animate from no shadow to a shadow?
Matt Perry
2015/06/30 22:09:11
We could, but that's extra code and we don't need
|
| + return null; |
| + |
| + int level1 = level.floor(); |
| + int level2 = level.ceil(); |
| + double t = level - level1.toDouble(); |
| + |
| + List<BoxShadow> shadow = new List<BoxShadow>(); |
| + for (int i = 0; i < shadows[level1].length; ++i) |
| + shadow.add(lerpShadow(shadows[level1][i], shadows[level2][i], t)); |
| + return shadow; |
| +} |
| + |
| +class Material extends AnimatedComponent { |
| Material({ |
| String key, |
| this.child, |
| this.edge: MaterialEdge.card, |
| - this.level: 0, |
| + int level: 0, |
| this.color |
| - }) : super(key: key); |
| + }) : super(key: key) { |
| + this.level = new AnimatedValue(level.toDouble()); |
| + animate(this.level, (_) {}); |
| + } |
| - final Widget child; |
| - final int level; |
| - final MaterialEdge edge; |
| - final Color color; |
| + Widget child; |
| + MaterialEdge edge; |
| + AnimatedValue level; |
| + Color color; |
| Color get backgroundColor { |
| if (color != null) |
| @@ -36,12 +77,21 @@ class Material extends Component { |
| } |
| } |
| - // TODO(ianh): we should make this animate level changes and color changes |
| + void syncFields(Material source) { |
| + child = source.child; |
| + edge = source.edge; |
| + if (level.value != source.level.value) |
| + level.animateTo(source.level.value.toDouble(), _kAnimateShadowDurationMS); |
| + color = source.color; |
| + super.syncFields(source); |
| + } |
| + |
| + // TODO(mpcomplete): make this animate color changes. |
| Widget build() { |
| return new Container( |
| decoration: new BoxDecoration( |
| - boxShadow: shadows[level], |
| + boxShadow: computeShadow(level.value), |
| borderRadius: edges[edge], |
| backgroundColor: backgroundColor, |
| shape: edge == MaterialEdge.circle ? Shape.circle : Shape.rectangle |