Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:sky' as sky; | 5 import 'dart:sky' as sky; |
| 6 | 6 |
| 7 import 'package:vector_math/vector_math.dart'; | |
| 8 import 'package:sky/animation/animation_performance.dart'; | 7 import 'package:sky/animation/animation_performance.dart'; |
| 9 import 'package:sky/widgets/animation_builder.dart'; | 8 import 'package:sky/widgets/animated.dart'; |
| 10 import 'package:sky/widgets/animated_component.dart'; | |
| 11 import 'package:sky/widgets/basic.dart'; | 9 import 'package:sky/widgets/basic.dart'; |
| 12 import 'package:sky/widgets/widget.dart'; | 10 import 'package:sky/widgets/widget.dart'; |
| 13 | 11 |
| 14 const int _kCardDismissFadeoutMS = 300; | 12 const Duration _kCardDismissFadeout = const Duration(milliseconds: 300); |
| 15 const double _kMinFlingVelocity = 700.0; | 13 const double _kMinFlingVelocity = 700.0; |
| 16 const double _kMinFlingVelocityDelta = 400.0; | 14 const double _kMinFlingVelocityDelta = 400.0; |
| 17 const double _kDismissCardThreshold = 0.6; | 15 const double _kDismissCardThreshold = 0.6; |
| 18 | 16 |
| 19 typedef void DismissedCallback(); | 17 typedef void DismissedCallback(); |
| 20 | 18 |
| 21 class Dismissable extends AnimatedComponent { | 19 class Dismissable extends StatefulComponent { |
| 22 | 20 |
| 23 Dismissable({ | 21 Dismissable({ |
| 24 String key, | 22 String key, |
| 25 this.child, | 23 this.child, |
| 26 this.onDismissed | 24 this.onDismissed |
| 27 // TODO(hansmuller): direction | 25 // TODO(hansmuller): direction |
| 28 }) : super(key: key); | 26 }) : super(key: key); |
| 29 | 27 |
| 30 Widget child; | 28 Widget child; |
| 31 DismissedCallback onDismissed; | 29 DismissedCallback onDismissed; |
| 32 | 30 |
| 33 AnimationBuilder _transform; | 31 AnimatedType<Point> _position; |
| 32 AnimatedType<double> _opacity; | |
| 34 AnimationPerformance _performance; | 33 AnimationPerformance _performance; |
| 34 | |
| 35 double _width; | 35 double _width; |
| 36 double _dragX = 0.0; | 36 double _dragX = 0.0; |
| 37 bool _dragUnderway = false; | 37 bool _dragUnderway = false; |
| 38 | 38 |
| 39 void initState() { | 39 void initState() { |
| 40 _transform = new AnimationBuilder() | 40 _position = new AnimatedType<Point>(Point.origin); |
| 41 ..position = new AnimatedType<Point>(Point.origin) | 41 _opacity = new AnimatedType<double>(1.0, end: 0.0); |
| 42 ..opacity = new AnimatedType<double>(1.0, end: 0.0); | 42 _performance = new AnimationPerformance() |
| 43 | 43 ..duration = _kCardDismissFadeout |
| 44 _performance = _transform.createPerformance( | 44 ..variable = new AnimatedList([_position, _opacity]) |
| 45 [_transform.position, _transform.opacity], | 45 ..addListener(_handleAnimationProgressChanged); |
| 46 duration: new Duration(milliseconds: _kCardDismissFadeoutMS)); | |
| 47 _performance.addListener(_handleAnimationProgressChanged); | |
| 48 watch(_performance); | |
| 49 } | 46 } |
| 50 | 47 |
| 51 void syncFields(Dismissable source) { | 48 void syncFields(Dismissable source) { |
| 52 child = source.child; | 49 child = source.child; |
| 53 onDismissed = source.onDismissed; | 50 onDismissed = source.onDismissed; |
| 54 super.syncFields(source); | |
| 55 } | 51 } |
| 56 | 52 |
| 57 Point get _activeCardDragEndPoint { | 53 Point get _activeCardDragEndPoint { |
| 58 assert(_width != null); | 54 assert(_width != null); |
| 59 return new Point(_dragX.sign * _width * _kDismissCardThreshold, 0.0); | 55 return new Point(_dragX.sign * _width * _kDismissCardThreshold, 0.0); |
| 60 } | 56 } |
| 61 | 57 |
| 62 bool get _isActive { | 58 bool get _isActive { |
| 63 return _width != null && (_dragUnderway || _performance.isAnimating); | 59 return _width != null && (_dragUnderway || _performance.isAnimating); |
| 64 } | 60 } |
| 65 | 61 |
| 66 void _maybeCallOnDismissed() { | 62 void _maybeCallOnDismissed() { |
| 67 if (onDismissed != null) | 63 if (onDismissed != null) |
| 68 onDismissed(); | 64 onDismissed(); |
| 69 } | 65 } |
| 70 | 66 |
| 71 void _handleAnimationProgressChanged() { | 67 void _handleAnimationProgressChanged() { |
| 72 setState(() { | 68 setState(() { |
| 73 if (_performance.isCompleted && !_dragUnderway) | 69 if (_performance.isCompleted && !_dragUnderway) |
| 74 _maybeCallOnDismissed(); | 70 _maybeCallOnDismissed(); |
| 75 }); | 71 }); |
| 76 } | 72 } |
| 77 | 73 |
| 78 void _handleSizeChanged(Size newSize) { | 74 void _handleSizeChanged(Size newSize) { |
| 79 _width = newSize.width; | 75 _width = newSize.width; |
| 80 _transform.position.end = _activeCardDragEndPoint; | 76 _position.end = _activeCardDragEndPoint; |
| 81 } | 77 } |
| 82 | 78 |
| 83 void _handlePointerDown(sky.PointerEvent event) { | 79 void _handlePointerDown(sky.PointerEvent event) { |
| 84 setState(() { | 80 setState(() { |
| 85 _dragUnderway = true; | 81 _dragUnderway = true; |
| 86 _dragX = 0.0; | 82 _dragX = 0.0; |
| 87 _performance.progress = 0.0; | 83 _performance.progress = 0.0; |
| 88 }); | 84 }); |
| 89 } | 85 } |
| 90 | 86 |
| 91 void _handlePointerMove(sky.PointerEvent event) { | 87 void _handlePointerMove(sky.PointerEvent event) { |
| 92 if (!_isActive) | 88 if (!_isActive) |
| 93 return; | 89 return; |
| 94 | 90 |
| 95 double oldDragX = _dragX; | 91 double oldDragX = _dragX; |
| 96 _dragX += event.dx; | 92 _dragX += event.dx; |
| 97 setState(() { | 93 setState(() { |
| 98 if (!_performance.isAnimating) { | 94 if (!_performance.isAnimating) { |
| 99 if (oldDragX.sign != _dragX.sign) | 95 if (oldDragX.sign != _dragX.sign) |
| 100 _transform.position.end = _activeCardDragEndPoint; | 96 _position.end = _activeCardDragEndPoint; |
| 101 _performance.progress = _dragX.abs() / (_width * _kDismissCardThreshold) ; | 97 _performance.progress = _dragX.abs() / (_width * _kDismissCardThreshold) ; |
| 102 } | 98 } |
| 103 }); | 99 }); |
| 104 } | 100 } |
| 105 | 101 |
| 106 void _handlePointerUpOrCancel(_) { | 102 void _handlePointerUpOrCancel(_) { |
| 107 if (!_isActive) | 103 if (!_isActive) |
| 108 return; | 104 return; |
| 109 | 105 |
| 110 setState(() { | 106 setState(() { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 123 } | 119 } |
| 124 | 120 |
| 125 void _handleFlingStart(sky.GestureEvent event) { | 121 void _handleFlingStart(sky.GestureEvent event) { |
| 126 if (!_isActive) | 122 if (!_isActive) |
| 127 return; | 123 return; |
| 128 | 124 |
| 129 if (_isHorizontalFlingGesture(event)) { | 125 if (_isHorizontalFlingGesture(event)) { |
| 130 _dragUnderway = false; | 126 _dragUnderway = false; |
| 131 double distance = 1.0 - _performance.progress; | 127 double distance = 1.0 - _performance.progress; |
| 132 if (distance > 0.0) { | 128 if (distance > 0.0) { |
| 133 double duration = _kCardDismissFadeoutMS * 1000.0 * distance / event.vel ocityX.abs(); | 129 double duration = _kCardDismissFadeout.inSeconds * distance / event.velo cityX.abs(); |
| 134 _dragX = event.velocityX.sign; | 130 _dragX = event.velocityX.sign; |
| 135 _performance.timeline.animateTo(1.0, duration: duration); | 131 _performance.timeline.animateTo(1.0, duration: duration); |
| 136 } | 132 } |
| 137 } | 133 } |
| 138 } | 134 } |
| 139 | 135 |
| 140 Widget build() { | 136 Widget build() { |
| 141 // TODO(hansmuller) The code below changes the widget tree when | |
| 142 // the user starts dragging. Currently this causes Sky to drop the | |
| 143 // rest of the pointer gesture, see https://github.com/domokit/mojo/issues/3 12. | |
| 144 // As a workaround, always create the Transform and Opacity nodes. | |
| 145 Widget transformedChild = child; | |
| 146 if (_isActive) { | |
| 147 transformedChild = _transform.build(transformedChild); | |
| 148 } else { | |
| 149 transformedChild = new Transform(child: transformedChild, transform: new M atrix4.identity()); | |
| 150 transformedChild = new Opacity(child: transformedChild, opacity: 1.0); | |
| 151 } | |
| 152 | |
| 153 return new Listener( | 137 return new Listener( |
| 154 onPointerDown: _handlePointerDown, | 138 onPointerDown: _handlePointerDown, |
| 155 onPointerMove: _handlePointerMove, | 139 onPointerMove: _handlePointerMove, |
| 156 onPointerUp: _handlePointerUpOrCancel, | 140 onPointerUp: _handlePointerUpOrCancel, |
| 157 onPointerCancel: _handlePointerUpOrCancel, | 141 onPointerCancel: _handlePointerUpOrCancel, |
| 158 onGestureFlingStart: _handleFlingStart, | 142 onGestureFlingStart: _handleFlingStart, |
| 159 child: new SizeObserver( | 143 child: new SizeObserver( |
| 160 child: transformedChild, | 144 callback: _handleSizeChanged, |
| 161 callback: _handleSizeChanged | 145 child: new PositionAnimation( |
| 146 position: _position, | |
| 147 performance: _performance, | |
| 148 child: new OpacityAnimation( | |
| 149 opacity: _opacity, | |
| 150 child: child | |
|
hansmuller
2015/07/15 00:38:04
The OpacityAnimation needs a performance too (as y
| |
| 151 ) | |
| 152 ) | |
| 162 ) | 153 ) |
| 163 ); | 154 ); |
| 164 } | 155 } |
| 165 } | 156 } |
| OLD | NEW |