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