| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 <!-- |  | 
| 2 // Copyright 2015 The Chromium Authors. All rights reserved. |  | 
| 3 // Use of this source code is governed by a BSD-style license that can be |  | 
| 4 // found in the LICENSE file. |  | 
| 5 --> |  | 
| 6 <import src="shadow.sky" as="shadow" /> |  | 
| 7 <import src="sky-element.sky" /> |  | 
| 8 <import src="sky-scrollable.sky" /> |  | 
| 9 |  | 
| 10 <sky-element attributes="level:number"> |  | 
| 11 <template> |  | 
| 12   <style> |  | 
| 13     #mask { |  | 
| 14       background-color: black; |  | 
| 15       will-change: opacity; |  | 
| 16       position: absolute; |  | 
| 17       top: 0; |  | 
| 18       left: 0; |  | 
| 19       bottom: 0; |  | 
| 20       right: 0; |  | 
| 21     } |  | 
| 22     #content { |  | 
| 23       background-color: #FAFAFA; |  | 
| 24       will-change: transform; |  | 
| 25       position: absolute; |  | 
| 26       z-index: 2; |  | 
| 27       width: 256px; |  | 
| 28       top: 0; |  | 
| 29       left: 0; |  | 
| 30       bottom: 0; |  | 
| 31     } |  | 
| 32   </style> |  | 
| 33   <div id="mask" /> |  | 
| 34   <div id="content"> |  | 
| 35     <content/> |  | 
| 36   </div> |  | 
| 37 </template> |  | 
| 38 <script> |  | 
| 39 import "animation/controller.dart"; |  | 
| 40 import "animation/curves.dart"; |  | 
| 41 import "animation/timer.dart"; |  | 
| 42 import "dart:math" as math; |  | 
| 43 import "dart:sky"; |  | 
| 44 |  | 
| 45 const double _kWidth = 256.0; |  | 
| 46 const double _kMinFlingVelocity = 0.4; |  | 
| 47 const double _kMinAnimationDurationMS = 246.0; |  | 
| 48 const double _kMaxAnimationDurationMS = 600.0; |  | 
| 49 const Cubic _kAnimationCurve = easeOut; |  | 
| 50 |  | 
| 51 @Tagname('sky-drawer') |  | 
| 52 class SkyDrawer extends SkyElement implements AnimationDelegate { |  | 
| 53   Element _mask; |  | 
| 54   Element _content; |  | 
| 55   double _position = 0.0; |  | 
| 56   AnimationController _animation; |  | 
| 57 |  | 
| 58   SkyDrawer() { |  | 
| 59     _animation = new AnimationController(this); |  | 
| 60 |  | 
| 61     addEventListener('pointerdown', _handlePointerDown); |  | 
| 62     addEventListener('pointermove', _handlePointerMove); |  | 
| 63     addEventListener('pointerup', _handlePointerUp); |  | 
| 64     addEventListener('pointercancel', _handlePointerCancel); |  | 
| 65   } |  | 
| 66 |  | 
| 67   void shadowRootReady() { |  | 
| 68     shadow.applyTo(shadowRoot); |  | 
| 69     _mask = shadowRoot.getElementById('mask'); |  | 
| 70     _mask.addEventListener('gesturetap', _handleMaskTap); |  | 
| 71     _content = shadowRoot.getElementById('content'); |  | 
| 72     _content.addEventListener('gestureflingstart', _handleFlingStart); |  | 
| 73     position = -_kWidth; |  | 
| 74   } |  | 
| 75 |  | 
| 76   void toggle() { |  | 
| 77     if (isMostlyClosed) |  | 
| 78       open(); |  | 
| 79     else |  | 
| 80       close(); |  | 
| 81   } |  | 
| 82 |  | 
| 83   void open() { |  | 
| 84     _animateToPosition(0.0); |  | 
| 85   } |  | 
| 86 |  | 
| 87   void close() { |  | 
| 88     _animateToPosition(-_kWidth); |  | 
| 89   } |  | 
| 90 |  | 
| 91   bool get isClosed => _position <= -_kWidth; |  | 
| 92   bool get isMostlyClosed => _position <= -_kWidth / 2; |  | 
| 93   double get position => _position; |  | 
| 94 |  | 
| 95   set position(double value) { |  | 
| 96     double newPosition = math.min(0.0, math.max(value, -_kWidth)); |  | 
| 97     _position = newPosition; |  | 
| 98     _content.style['transform'] = 'translateX(${newPosition}px)'; |  | 
| 99     _mask.style['opacity'] = '${(newPosition / _kWidth + 1) * 0.25}'; |  | 
| 100     style['display'] = isClosed ? 'none' : ''; |  | 
| 101   } |  | 
| 102 |  | 
| 103   void _settle() { |  | 
| 104     if (isMostlyClosed) |  | 
| 105       close(); |  | 
| 106     else |  | 
| 107       open(); |  | 
| 108   } |  | 
| 109 |  | 
| 110   void _animateToPosition(double targetPosition) { |  | 
| 111     double currentPosition = _position; |  | 
| 112     double distance = (targetPosition - currentPosition).abs(); |  | 
| 113     double duration = _kMaxAnimationDurationMS * distance / _kWidth; |  | 
| 114     _animation.start( |  | 
| 115       begin: currentPosition, |  | 
| 116       end: targetPosition, |  | 
| 117       duration: math.max(_kMinAnimationDurationMS, duration), |  | 
| 118       curve: _kAnimationCurve); |  | 
| 119   } |  | 
| 120 |  | 
| 121   void updateAnimation(double p) { |  | 
| 122     position = p; |  | 
| 123   } |  | 
| 124 |  | 
| 125   void _handleMaskTap(_) { |  | 
| 126     close(); |  | 
| 127   } |  | 
| 128 |  | 
| 129   void _handlePointerDown(_) { |  | 
| 130     _animation.stop(); |  | 
| 131   } |  | 
| 132 |  | 
| 133   void _handlePointerMove(PointerEvent event) { |  | 
| 134     position += event.dx; |  | 
| 135   } |  | 
| 136 |  | 
| 137   void _handlePointerUp(_) { |  | 
| 138     if (!_animation.isAnimating) |  | 
| 139       _settle(); |  | 
| 140   } |  | 
| 141 |  | 
| 142   void _handlePointerCancel(_) { |  | 
| 143     if (!_animation.isAnimating) |  | 
| 144       _settle(); |  | 
| 145   } |  | 
| 146 |  | 
| 147   void _handleFlingStart(event) { |  | 
| 148     double direction = event.velocityX.sign; |  | 
| 149     double velocityX = event.velocityX.abs() / 1000; |  | 
| 150     if (velocityX < _kMinFlingVelocity) |  | 
| 151       return; |  | 
| 152     double targetPosition = direction < 0.0 ? -kWidth : 0.0; |  | 
| 153     double currentPosition = _position; |  | 
| 154     double distance = (targetPosition - currentPosition).abs(); |  | 
| 155     double duration = distance / velocityX; |  | 
| 156     _animation.start( |  | 
| 157       begin: currentPosition, |  | 
| 158       end: targetPosition, |  | 
| 159       duration: duration, |  | 
| 160       curve: linear); |  | 
| 161   } |  | 
| 162 } |  | 
| 163 |  | 
| 164 _init(script) => register(script, SkyDrawer); |  | 
| 165 </script> |  | 
| 166 </sky-element> |  | 
| OLD | NEW | 
|---|