| 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:math' as math; | |
| 6 import 'mechanics.dart'; | |
| 7 import 'generators.dart'; | |
| 8 | |
| 9 const double _kScrollFriction = 0.005; | |
| 10 const double _kOverscrollFriction = 0.075; | |
| 11 const double _kBounceSlopeAngle = math.PI / 512.0; // radians | |
| 12 | |
| 13 abstract class ScrollBehavior { | |
| 14 Simulation release(Particle particle) => null; | |
| 15 | |
| 16 // Returns the new scroll offset. | |
| 17 double applyCurve(double scrollOffset, double scrollDelta); | |
| 18 } | |
| 19 | |
| 20 class BoundedScrollBehavior extends ScrollBehavior { | |
| 21 double minOffset; | |
| 22 double maxOffset; | |
| 23 | |
| 24 BoundedScrollBehavior({this.minOffset: 0.0, this.maxOffset}); | |
| 25 | |
| 26 double applyCurve(double scrollOffset, double scrollDelta) { | |
| 27 double newScrollOffset = scrollOffset + scrollDelta; | |
| 28 if (minOffset != null) | |
| 29 newScrollOffset = math.max(minOffset, newScrollOffset); | |
| 30 if (maxOffset != null) | |
| 31 newScrollOffset = math.min(maxOffset, newScrollOffset); | |
| 32 return newScrollOffset; | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 class OverscrollBehavior extends ScrollBehavior { | |
| 37 | |
| 38 double _contentsHeight; | |
| 39 double get contentsHeight => _contentsHeight; | |
| 40 void set contentsHeight (double value) { | |
| 41 if (_contentsHeight != value) { | |
| 42 _contentsHeight = value; | |
| 43 // TODO(ianh) now what? what if we have a simulation ongoing? | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 double _containerHeight; | |
| 48 double get containerHeight => _containerHeight; | |
| 49 void set containerHeight (double value) { | |
| 50 if (_containerHeight != value) { | |
| 51 _containerHeight = value; | |
| 52 // TODO(ianh) now what? what if we have a simulation ongoing? | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 OverscrollBehavior({double contentsHeight: 0.0, double containerHeight: 0.0}) | |
| 57 : _contentsHeight = contentsHeight, | |
| 58 _containerHeight = containerHeight; | |
| 59 | |
| 60 double get maxScroll => math.max(0.0, _contentsHeight - _containerHeight); | |
| 61 | |
| 62 Simulation release(Particle particle) { | |
| 63 System system; | |
| 64 if ((particle.position >= 0.0) && (particle.position < maxScroll)) { | |
| 65 if (particle.velocity == 0.0) | |
| 66 return null; | |
| 67 System slowdownSystem = new ParticleInBoxWithFriction( | |
| 68 particle: particle, | |
| 69 friction: _kScrollFriction, | |
| 70 box: new GeofenceBox(min: 0.0, max: maxScroll, onEscape: () { | |
| 71 (system as Multisystem).transitionToSystem(new ParticleInBoxWithFricti
on( | |
| 72 particle: particle, | |
| 73 friction: _kOverscrollFriction, | |
| 74 box: new ClosedBox(), | |
| 75 onStop: () => (system as Multisystem).transitionToSystem(getBounceBa
ckSystem(particle)) | |
| 76 )); | |
| 77 })); | |
| 78 system = new Multisystem(particle: particle, system: slowdownSystem); | |
| 79 } else { | |
| 80 system = getBounceBackSystem(particle); | |
| 81 } | |
| 82 return new Simulation(system, terminationCondition: () => particle.position
== 0.0); | |
| 83 } | |
| 84 | |
| 85 System getBounceBackSystem(Particle particle) { | |
| 86 if (particle.position < 0.0) | |
| 87 return new ParticleClimbingRamp( | |
| 88 particle: particle, | |
| 89 box: new ClosedBox(max: 0.0), | |
| 90 theta: _kBounceSlopeAngle, | |
| 91 targetPosition: 0.0); | |
| 92 return new ParticleClimbingRamp( | |
| 93 particle: particle, | |
| 94 box: new ClosedBox(min: maxScroll), | |
| 95 theta: _kBounceSlopeAngle, | |
| 96 targetPosition: maxScroll); | |
| 97 } | |
| 98 | |
| 99 double applyCurve(double scrollOffset, double scrollDelta) { | |
| 100 double newScrollOffset = scrollOffset + scrollDelta; | |
| 101 // If we're overscrolling, we want move the scroll offset 2x | |
| 102 // slower than we would otherwise. Therefore, we "rewind" the | |
| 103 // newScrollOffset by half the amount that we moved it above. | |
| 104 // Notice that we clap the "old" value to 0.0 so that we only | |
| 105 // reduce the portion of scrollDelta that's applied beyond 0.0. We | |
| 106 // do similar things for overscroll in the other direction. | |
| 107 if (newScrollOffset < 0.0) { | |
| 108 newScrollOffset -= (newScrollOffset - math.min(0.0, scrollOffset)) / 2.0; | |
| 109 } else if (newScrollOffset > maxScroll) { | |
| 110 newScrollOffset -= (newScrollOffset - math.max(maxScroll, scrollOffset)) /
2.0; | |
| 111 } | |
| 112 return newScrollOffset; | |
| 113 } | |
| 114 } | |
| OLD | NEW |