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

Unified 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, 10 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
« no previous file with comments | « sky/examples/fn/widgets/checkbox.dart ('k') | sky/examples/fn/widgets/drawerheader.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/examples/fn/widgets/drawer.dart
diff --git a/sky/examples/fn/widgets/drawer.dart b/sky/examples/fn/widgets/drawer.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ee0c58b38d015b09320b056ca926ce20f747b187
--- /dev/null
+++ b/sky/examples/fn/widgets/drawer.dart
@@ -0,0 +1,199 @@
+part of widgets;
+
+const double _kWidth = 256.0;
+const double _kMinFlingVelocity = 0.4;
+const double _kMinAnimationDurationMS = 246.0;
+const double _kMaxAnimationDurationMS = 600.0;
+const Cubic _kAnimationCurve = easeOut;
+
+class DrawerAnimation {
+
+ Stream<double> get onPositionChanged => _controller.stream;
+
+ StreamController _controller;
+ AnimationGenerator _animation;
+ double _position;
+ bool get _isAnimating => _animation != null;
+ bool get _isMostlyClosed => _position <= -_kWidth / 2;
+
+ DrawerAnimation() {
+ _controller = new StreamController(sync: true);
+ _setPosition(-_kWidth);
+ }
+
+ void toggle(_) => _isMostlyClosed ? _open() : _close();
+
+ void handleMaskTap(_) => _close();
+
+ void handlePointerDown(_) => _cancelAnimation();
+
+ void handlePointerMove(sky.PointerEvent event) {
+ assert(_animation == null);
+ _setPosition(_position + event.dx);
+ }
+
+ void handlePointerUp(_) {
+ if (!_isAnimating)
+ _settle();
+ }
+
+ void handlePointerCancel(_) {
+ if (!_isAnimating)
+ _settle();
+ }
+
+ void _open() => _animateToPosition(0.0);
+
+ void _close() => _animateToPosition(-_kWidth);
+
+ void _settle() => _isMostlyClosed ? _close() : _open();
+
+ void _setPosition(double value) {
+ _position = math.min(0.0, math.max(value, -_kWidth));
+ _controller.add(_position);
+ }
+
+ void _cancelAnimation() {
+ if (_animation != null) {
+ _animation.cancel();
+ _animation = null;
+ }
+ }
+
+ void _animate(double duration, double begin, double end, Curve curve) {
+ _cancelAnimation();
+
+ _animation = new AnimationGenerator(duration, begin: begin, end: end,
+ curve: curve);
+
+ _animation.onTick.listen(_setPosition, onDone: () {
+ _animation = null;
+ });
+ }
+
+ void _animateToPosition(double targetPosition) {
+ double distance = (targetPosition - _position).abs();
+ double duration = math.max(
+ _kMinAnimationDurationMS,
+ _kMaxAnimationDurationMS * distance / _kWidth);
+
+ _animate(duration, _position, targetPosition, _kAnimationCurve);
+ }
+
+ void handleFlingStart(event) {
+ double direction = event.velocityX.sign;
+ double velocityX = event.velocityX.abs() / 1000;
+ if (velocityX < _kMinFlingVelocity)
+ return;
+
+ double targetPosition = direction < 0.0 ? -_kWidth : 0.0;
+ double distance = (targetPosition - _position).abs();
+ double duration = distance / velocityX;
+
+ _animate(duration, _position, targetPosition, linear);
+ }
+}
+
+class Drawer extends Component {
+
+ static Style _style = new Style('''
+ position: absolute;
+ z-index: 2;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);'''
+ );
+
+ static Style _maskStyle = new Style('''
+ background-color: black;
+ will-change: opacity;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;'''
+ );
+
+ static Style _contentStyle = new Style('''
+ background-color: #FAFAFA;
+ will-change: transform;
+ position: absolute;
+ width: 256px;
+ top: 0;
+ left: 0;
+ bottom: 0;'''
+ );
+
+ Stream<double> onPositionChanged;
+ sky.EventListener handleMaskFling;
+ sky.EventListener handleMaskTap;
+ sky.EventListener handlePointerCancel;
+ sky.EventListener handlePointerDown;
+ sky.EventListener handlePointerMove;
+ sky.EventListener handlePointerUp;
+ List<Node> children;
+
+ Drawer({
+ Object key,
+ this.onPositionChanged,
+ this.handleMaskFling,
+ this.handleMaskTap,
+ this.handlePointerCancel,
+ this.handlePointerDown,
+ this.handlePointerMove,
+ this.handlePointerUp,
+ this.children
+ }) : super(key: key);
+
+ double _position = -_kWidth;
+
+ bool _listening = false;
+
+ void _ensureListening() {
+ if (_listening)
+ return;
+
+ _listening = true;
+ onPositionChanged.listen((position) {
+ setState(() {
+ _position = position;
+ });
+ });
+ }
+
+ Node render() {
+ _ensureListening();
+
+ bool isClosed = _position <= -_kWidth;
+ String inlineStyle = 'display: ${isClosed ? 'none' : ''}';
+ String maskInlineStyle = 'opacity: ${(_position / _kWidth + 1) * 0.25}';
+ String contentInlineStyle = 'transform: translateX(${_position}px)';
+
+ return new Container(
+ style: _style,
+ inlineStyle: inlineStyle,
+ onPointerDown: handlePointerDown,
+ onPointerMove: handlePointerMove,
+ onPointerUp: handlePointerUp,
+ onPointerCancel: handlePointerCancel,
+
+ children: [
+ new Container(
+ key: 'Mask',
+ style: _maskStyle,
+ inlineStyle: maskInlineStyle,
+ onGestureTap: handleMaskTap,
+ onFlingStart: handleMaskFling
+ ),
+ new Container(
+ key: 'Content',
+ style: _contentStyle,
+ inlineStyle: contentInlineStyle,
+ children: children
+ )
+ ]
+ );
+ }
+}
« 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