Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1100)

Unified Diff: sky/sdk/lib/widgets/animated_container.dart

Issue 1223073002: AnimatedContainer: generalized Container widget that handles animating values (Closed) Base URL: git@github.com:/domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sky/sdk/lib/widgets/animated_container.dart
diff --git a/sky/sdk/lib/widgets/animated_container.dart b/sky/sdk/lib/widgets/animated_container.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9248785e44ec7f6a9554cba2c282cb977cc0e008
--- /dev/null
+++ b/sky/sdk/lib/widgets/animated_container.dart
@@ -0,0 +1,140 @@
+// 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.
+
+import 'dart:async';
+
+import 'package:vector_math/vector_math.dart';
+
+import '../animation/animation_performance.dart';
+import '../animation/curves.dart';
+import '../base/lerp.dart';
+import '../painting/box_painter.dart';
+import '../theme/shadows.dart';
+import 'animated_component.dart';
+import 'basic.dart';
+
+// Types of things that can be animated in a component. Use build() to
+// construct the final Widget based on the animation state.
+// TODO(mpcomplete): the idea here is to eventually have an AnimatedCollection
+// which assembles a container based on a list of animated things. e.g. if you
+// want to animate position, opacity, and shadow, you add those animators to an
+// AnimatedCollection and just call collection.build() to construct your
+// widget.
+
+List<BoxShadow> _computeShadow(double level) {
+ if (level < 1.0) // shadows[1] is the first shadow
+ 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(lerpBoxShadow(shadows[level1][i], shadows[level2][i], t));
+ return shadow;
+}
+
+class AnimatedColor extends AnimatedType<Color> {
+ AnimatedColor(Color begin, {Color end, Curve curve: linear})
+ : super(begin, end: end, curve: curve);
+
+ void setFraction(double t) {
+ value = lerpColor(begin, end, t);
+ }
+}
+
+enum AnimatedContainerSlots {
+ position,
+ shadow,
+ backgroundColor
+}
abarth-chromium 2015/07/08 21:02:05 This seems overly general. Why not just use expli
Matt Perry 2015/07/08 21:41:03 Done.
+
+class _Entry {
+ AnimatedType variable;
+ AnimationPerformance performance;
+}
+
+class AnimatedContainer {
+ AnimatedType<Point> get position => _getSlot(AnimatedContainerSlots.position);
+ void set position(AnimatedType<Point> variable) {
+ _setSlot(AnimatedContainerSlots.position, variable);
+ }
+ AnimatedType<double> get shadow => _getSlot(AnimatedContainerSlots.shadow);
+ void set shadow(AnimatedType<double> variable) {
+ _setSlot(AnimatedContainerSlots.shadow, variable);
+ }
+ AnimatedColor get backgroundColor => _getSlot(AnimatedContainerSlots.backgroundColor);
+ void set backgroundColor(AnimatedColor variable) {
+ _setSlot(AnimatedContainerSlots.backgroundColor, variable);
+ }
+
+ AnimatedType _getSlot(AnimatedContainerSlots slot) {
+ if (_slots[slot] == null)
+ return null;
+ return _slots[slot].variable;
+ }
+ void _setSlot(AnimatedContainerSlots slot, AnimatedType variable) {
+ _slots[slot] = new _Entry()..variable = variable;
+ }
+
+ Map<AnimatedContainerSlots, _Entry> _slots =
+ new Map<AnimatedContainerSlots, _Entry>();
+ List<AnimationPerformance> _performances = [];
+
+ // TODO(mpcomplete): don't rely on AnimatedComponent.
+ AnimatedComponent _component;
+ AnimatedContainer([this._component]);
+
+ AnimationPerformance createPerformance(List<AnimatedContainerSlots> slots,
+ {Duration duration}) {
+ List<AnimatedVariable> variables = slots.map((e) => _slots[e].variable).toList();
+ AnimationPerformance performance = new AnimationPerformance()
+ ..duration = duration
+ ..variable = new AnimatedList(variables);
+ _performances.add(performance);
+ for (AnimatedContainerSlots slot in slots)
+ _slots[slot].performance = performance;
+ if (_component != null)
+ _component.watch(performance.timeline);
+ return performance;
+ }
+
+ Widget build(Widget child) {
+ Widget current = child;
+ if (shadow != null || backgroundColor != null) {
+ current = new DecoratedBox(
+ decoration: new BoxDecoration(
+ boxShadow: shadow != null ? _computeShadow(shadow.value) : null,
+ backgroundColor: backgroundColor != null ? backgroundColor.value : null),
+ child: current);
+ }
+
+ if (position != null) {
+ Matrix4 transform = new Matrix4.identity();
+ transform.translate(position.value.x, position.value.y);
+ current = new Transform(transform: transform, child: child);
+ }
+
+ return current;
+ }
+
+ bool syncFields(AnimatedContainer source) {
+ for (AnimatedContainerSlots slot in AnimatedContainerSlots.values) {
+ if (_slots[slot] == null)
+ continue; // TODO(mpcomplete): Should we handle transition from null?
+ if (_slots[slot].performance == null) {
+ // If there's no performance, no need to animate.
+ _slots[slot].variable = source._slots[slot].variable;
+ } else if (_slots[slot].variable.value != source._slots[slot].variable.value) {
+ _slots[slot].variable
+ ..begin = _slots[slot].variable.value
+ ..end = source._slots[slot].variable.value;
+ _slots[slot].performance
+ ..progress = 0.0
+ ..play();
+ }
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698