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

Side by Side Diff: sky/examples/fn/widgets/drawer.dart

Issue 971183002: Initial commit of Effen reactive framework experiment for Sky (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 9 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 unified diff | Download patch
« no previous file with comments | « sky/examples/fn/widgets/checkbox.dart ('k') | sky/examples/fn/widgets/drawerheader.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 part of widgets;
2
3 const double _kWidth = 256.0;
4 const double _kMinFlingVelocity = 0.4;
5 const double _kMinAnimationDurationMS = 246.0;
6 const double _kMaxAnimationDurationMS = 600.0;
7 const Cubic _kAnimationCurve = easeOut;
8
9 class DrawerAnimation {
10
11 Stream<double> get onPositionChanged => _controller.stream;
12
13 StreamController _controller;
14 AnimationGenerator _animation;
15 double _position;
16 bool get _isAnimating => _animation != null;
17 bool get _isMostlyClosed => _position <= -_kWidth / 2;
18
19 DrawerAnimation() {
20 _controller = new StreamController(sync: true);
21 _setPosition(-_kWidth);
22 }
23
24 void toggle(_) => _isMostlyClosed ? _open() : _close();
25
26 void handleMaskTap(_) => _close();
27
28 void handlePointerDown(_) => _cancelAnimation();
29
30 void handlePointerMove(sky.PointerEvent event) {
31 assert(_animation == null);
32 _setPosition(_position + event.dx);
33 }
34
35 void handlePointerUp(_) {
36 if (!_isAnimating)
37 _settle();
38 }
39
40 void handlePointerCancel(_) {
41 if (!_isAnimating)
42 _settle();
43 }
44
45 void _open() => _animateToPosition(0.0);
46
47 void _close() => _animateToPosition(-_kWidth);
48
49 void _settle() => _isMostlyClosed ? _close() : _open();
50
51 void _setPosition(double value) {
52 _position = math.min(0.0, math.max(value, -_kWidth));
53 _controller.add(_position);
54 }
55
56 void _cancelAnimation() {
57 if (_animation != null) {
58 _animation.cancel();
59 _animation = null;
60 }
61 }
62
63 void _animate(double duration, double begin, double end, Curve curve) {
64 _cancelAnimation();
65
66 _animation = new AnimationGenerator(duration, begin: begin, end: end,
67 curve: curve);
68
69 _animation.onTick.listen(_setPosition, onDone: () {
70 _animation = null;
71 });
72 }
73
74 void _animateToPosition(double targetPosition) {
75 double distance = (targetPosition - _position).abs();
76 double duration = math.max(
77 _kMinAnimationDurationMS,
78 _kMaxAnimationDurationMS * distance / _kWidth);
79
80 _animate(duration, _position, targetPosition, _kAnimationCurve);
81 }
82
83 void handleFlingStart(event) {
84 double direction = event.velocityX.sign;
85 double velocityX = event.velocityX.abs() / 1000;
86 if (velocityX < _kMinFlingVelocity)
87 return;
88
89 double targetPosition = direction < 0.0 ? -_kWidth : 0.0;
90 double distance = (targetPosition - _position).abs();
91 double duration = distance / velocityX;
92
93 _animate(duration, _position, targetPosition, linear);
94 }
95 }
96
97 class Drawer extends Component {
98
99 static Style _style = new Style('''
100 position: absolute;
101 z-index: 2;
102 top: 0;
103 left: 0;
104 bottom: 0;
105 right: 0;
106 box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);'''
107 );
108
109 static Style _maskStyle = new Style('''
110 background-color: black;
111 will-change: opacity;
112 position: absolute;
113 top: 0;
114 left: 0;
115 bottom: 0;
116 right: 0;'''
117 );
118
119 static Style _contentStyle = new Style('''
120 background-color: #FAFAFA;
121 will-change: transform;
122 position: absolute;
123 width: 256px;
124 top: 0;
125 left: 0;
126 bottom: 0;'''
127 );
128
129 Stream<double> onPositionChanged;
130 sky.EventListener handleMaskFling;
131 sky.EventListener handleMaskTap;
132 sky.EventListener handlePointerCancel;
133 sky.EventListener handlePointerDown;
134 sky.EventListener handlePointerMove;
135 sky.EventListener handlePointerUp;
136 List<Node> children;
137
138 Drawer({
139 Object key,
140 this.onPositionChanged,
141 this.handleMaskFling,
142 this.handleMaskTap,
143 this.handlePointerCancel,
144 this.handlePointerDown,
145 this.handlePointerMove,
146 this.handlePointerUp,
147 this.children
148 }) : super(key: key);
149
150 double _position = -_kWidth;
151
152 bool _listening = false;
153
154 void _ensureListening() {
155 if (_listening)
156 return;
157
158 _listening = true;
159 onPositionChanged.listen((position) {
160 setState(() {
161 _position = position;
162 });
163 });
164 }
165
166 Node render() {
167 _ensureListening();
168
169 bool isClosed = _position <= -_kWidth;
170 String inlineStyle = 'display: ${isClosed ? 'none' : ''}';
171 String maskInlineStyle = 'opacity: ${(_position / _kWidth + 1) * 0.25}';
172 String contentInlineStyle = 'transform: translateX(${_position}px)';
173
174 return new Container(
175 style: _style,
176 inlineStyle: inlineStyle,
177 onPointerDown: handlePointerDown,
178 onPointerMove: handlePointerMove,
179 onPointerUp: handlePointerUp,
180 onPointerCancel: handlePointerCancel,
181
182 children: [
183 new Container(
184 key: 'Mask',
185 style: _maskStyle,
186 inlineStyle: maskInlineStyle,
187 onGestureTap: handleMaskTap,
188 onFlingStart: handleMaskFling
189 ),
190 new Container(
191 key: 'Content',
192 style: _contentStyle,
193 inlineStyle: contentInlineStyle,
194 children: children
195 )
196 ]
197 );
198 }
199 }
OLDNEW
« no previous file with comments | « sky/examples/fn/widgets/checkbox.dart ('k') | sky/examples/fn/widgets/drawerheader.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698