Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 | |
| 7 import 'package:vector_math/vector_math.dart'; | |
| 8 | |
| 9 import '../animation/animation_performance.dart'; | |
| 10 import '../animation/curves.dart'; | |
| 11 import '../base/lerp.dart'; | |
| 12 import '../painting/box_painter.dart'; | |
| 13 import '../theme/shadows.dart'; | |
| 14 import 'animated_component.dart'; | |
| 15 import 'basic.dart'; | |
| 16 | |
| 17 // Types of things that can be animated in a component. Use build() to | |
| 18 // construct the final Widget based on the animation state. | |
| 19 // TODO(mpcomplete): the idea here is to eventually have an AnimatedCollection | |
| 20 // which assembles a container based on a list of animated things. e.g. if you | |
| 21 // want to animate position, opacity, and shadow, you add those animators to an | |
| 22 // AnimatedCollection and just call collection.build() to construct your | |
| 23 // widget. | |
| 24 | |
| 25 List<BoxShadow> _computeShadow(double level) { | |
| 26 if (level < 1.0) // shadows[1] is the first shadow | |
| 27 return null; | |
| 28 | |
| 29 int level1 = level.floor(); | |
| 30 int level2 = level.ceil(); | |
| 31 double t = level - level1.toDouble(); | |
| 32 | |
| 33 List<BoxShadow> shadow = new List<BoxShadow>(); | |
| 34 for (int i = 0; i < shadows[level1].length; ++i) | |
| 35 shadow.add(lerpBoxShadow(shadows[level1][i], shadows[level2][i], t)); | |
| 36 return shadow; | |
| 37 } | |
| 38 | |
| 39 class AnimatedColor extends AnimatedType<Color> { | |
| 40 AnimatedColor(Color begin, {Color end, Curve curve: linear}) | |
| 41 : super(begin, end: end, curve: curve); | |
| 42 | |
| 43 void setFraction(double t) { | |
| 44 value = lerpColor(begin, end, t); | |
| 45 } | |
| 46 } | |
| 47 | |
| 48 enum AnimatedContainerSlots { | |
| 49 position, | |
| 50 shadow, | |
| 51 backgroundColor | |
| 52 } | |
|
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.
| |
| 53 | |
| 54 class _Entry { | |
| 55 AnimatedType variable; | |
| 56 AnimationPerformance performance; | |
| 57 } | |
| 58 | |
| 59 class AnimatedContainer { | |
| 60 AnimatedType<Point> get position => _getSlot(AnimatedContainerSlots.position); | |
| 61 void set position(AnimatedType<Point> variable) { | |
| 62 _setSlot(AnimatedContainerSlots.position, variable); | |
| 63 } | |
| 64 AnimatedType<double> get shadow => _getSlot(AnimatedContainerSlots.shadow); | |
| 65 void set shadow(AnimatedType<double> variable) { | |
| 66 _setSlot(AnimatedContainerSlots.shadow, variable); | |
| 67 } | |
| 68 AnimatedColor get backgroundColor => _getSlot(AnimatedContainerSlots.backgroun dColor); | |
| 69 void set backgroundColor(AnimatedColor variable) { | |
| 70 _setSlot(AnimatedContainerSlots.backgroundColor, variable); | |
| 71 } | |
| 72 | |
| 73 AnimatedType _getSlot(AnimatedContainerSlots slot) { | |
| 74 if (_slots[slot] == null) | |
| 75 return null; | |
| 76 return _slots[slot].variable; | |
| 77 } | |
| 78 void _setSlot(AnimatedContainerSlots slot, AnimatedType variable) { | |
| 79 _slots[slot] = new _Entry()..variable = variable; | |
| 80 } | |
| 81 | |
| 82 Map<AnimatedContainerSlots, _Entry> _slots = | |
| 83 new Map<AnimatedContainerSlots, _Entry>(); | |
| 84 List<AnimationPerformance> _performances = []; | |
| 85 | |
| 86 // TODO(mpcomplete): don't rely on AnimatedComponent. | |
| 87 AnimatedComponent _component; | |
| 88 AnimatedContainer([this._component]); | |
| 89 | |
| 90 AnimationPerformance createPerformance(List<AnimatedContainerSlots> slots, | |
| 91 {Duration duration}) { | |
| 92 List<AnimatedVariable> variables = slots.map((e) => _slots[e].variable).toLi st(); | |
| 93 AnimationPerformance performance = new AnimationPerformance() | |
| 94 ..duration = duration | |
| 95 ..variable = new AnimatedList(variables); | |
| 96 _performances.add(performance); | |
| 97 for (AnimatedContainerSlots slot in slots) | |
| 98 _slots[slot].performance = performance; | |
| 99 if (_component != null) | |
| 100 _component.watch(performance.timeline); | |
| 101 return performance; | |
| 102 } | |
| 103 | |
| 104 Widget build(Widget child) { | |
| 105 Widget current = child; | |
| 106 if (shadow != null || backgroundColor != null) { | |
| 107 current = new DecoratedBox( | |
| 108 decoration: new BoxDecoration( | |
| 109 boxShadow: shadow != null ? _computeShadow(shadow.value) : null, | |
| 110 backgroundColor: backgroundColor != null ? backgroundColor.value : nul l), | |
| 111 child: current); | |
| 112 } | |
| 113 | |
| 114 if (position != null) { | |
| 115 Matrix4 transform = new Matrix4.identity(); | |
| 116 transform.translate(position.value.x, position.value.y); | |
| 117 current = new Transform(transform: transform, child: child); | |
| 118 } | |
| 119 | |
| 120 return current; | |
| 121 } | |
| 122 | |
| 123 bool syncFields(AnimatedContainer source) { | |
| 124 for (AnimatedContainerSlots slot in AnimatedContainerSlots.values) { | |
| 125 if (_slots[slot] == null) | |
| 126 continue; // TODO(mpcomplete): Should we handle transition from null? | |
| 127 if (_slots[slot].performance == null) { | |
| 128 // If there's no performance, no need to animate. | |
| 129 _slots[slot].variable = source._slots[slot].variable; | |
| 130 } else if (_slots[slot].variable.value != source._slots[slot].variable.val ue) { | |
| 131 _slots[slot].variable | |
| 132 ..begin = _slots[slot].variable.value | |
| 133 ..end = source._slots[slot].variable.value; | |
| 134 _slots[slot].performance | |
| 135 ..progress = 0.0 | |
| 136 ..play(); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 } | |
| OLD | NEW |