| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:math' as math; |
| import 'mechanics.dart'; |
| import 'generators.dart'; |
| |
| const double _kSlope = 0.02; |
| const double _kFriction = 0.004; |
| |
| abstract class ScrollBehavior { |
| Simulation release(Particle particle) => null; |
| |
| // Returns the new scroll offset. |
| double applyCurve(double scrollOffset, double scrollDelta); |
| } |
| |
| class BoundedScrollBehavior extends ScrollBehavior { |
| double minOffset; |
| double maxOffset; |
| |
| BoundedScrollBehavior({this.minOffset: 0.0, this.maxOffset}); |
| |
| double applyCurve(double scrollOffset, double scrollDelta) { |
| double newScrollOffset = scrollOffset + scrollDelta; |
| if (minOffset != null) |
| newScrollOffset = math.max(minOffset, newScrollOffset); |
| if (maxOffset != null) |
| newScrollOffset = math.min(maxOffset, newScrollOffset); |
| return newScrollOffset; |
| } |
| } |
| |
| class OverscrollBehavior extends ScrollBehavior { |
| Simulation release(Particle particle) { |
| if (particle.position >= 0.0) { |
| if (particle.velocity == 0.0) |
| return null; |
| System system = new ParticleInBoxWithFriction( |
| particle: particle, |
| box: new Box(min: 0.0), |
| friction: _kFriction); |
| return new Simulation(system, |
| terminationCondition: () => particle.velocity == 0.0); |
| } |
| System system = new ParticleClimbingRamp( |
| particle: particle, |
| box: new Box(max: 0.0), |
| slope: _kSlope, |
| targetPosition: 0.0); |
| return new Simulation(system, |
| terminationCondition: () => particle.position == 0.0); |
| } |
| |
| double applyCurve(double scrollOffset, double scrollDelta) { |
| double newScrollOffset = scrollOffset + scrollDelta; |
| if (newScrollOffset < 0.0) { |
| // If we're overscrolling, we want move the scroll offset 2x slower than |
| // we would otherwise. Therefore, we "rewind" the newScrollOffset by half |
| // the amount that we moved it above. Notice that we clap the "old" value |
| // to 0.0 so that we only reduce the portion of scrollDelta that's applied |
| // beyond 0.0. |
| newScrollOffset -= (newScrollOffset - math.min(0.0, scrollOffset)) / 2.0; |
| } |
| return newScrollOffset; |
| } |
| } |