scroll_simulation.dart 2.87 KB
Newer Older
1
// Copyright 2016 The Chromium Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7 8
import 'friction_simulation.dart';
import 'simulation_group.dart';
import 'simulation.dart';
import 'spring_simulation.dart';
9

Ian Hickson's avatar
Ian Hickson committed
10 11
/// Composite simulation for scrollable interfaces.
///
12
/// Simulates kinetic scrolling behavior between a leading and trailing
Ian Hickson's avatar
Ian Hickson committed
13 14
/// boundary. Friction is applied within the extents and a spring action is
/// applied at the boundaries. This simulation can only step forward.
15
class ScrollSimulation extends SimulationGroup {
Ian Hickson's avatar
Ian Hickson committed
16 17 18 19 20 21 22 23 24 25 26 27 28
  /// Creates a [ScrollSimulation] with the given parameters.
  ///
  /// The position and velocity arguments must use the same units as will be
  /// expected from the [x] and [dx] methods respectively.
  ///
  /// The leading and trailing extents must use the unit of length, the same
  /// unit as used for the position argument and as expected from the [x]
  /// method.
  ///
  /// The units used with the provided [SpringDescription] must similarly be
  /// consistent with the other arguments.
  ///
  /// The final argument is the coefficient of friction, which is unitless.
29 30 31 32 33 34 35 36 37 38
  ScrollSimulation(
    double position,
    double velocity,
    this._leadingExtent,
    this._trailingExtent,
    this._spring,
    this._drag) {
    _chooseSimulation(position, velocity, 0.0);
  }

39 40
  final double _leadingExtent;
  final double _trailingExtent;
41
  final SpringDescription _spring;
42 43 44 45
  final double _drag;

  bool _isSpringing = false;
  Simulation _currentSimulation;
46
  double _offset = 0.0;
47 48

  @override
49
  bool step(double time) => _chooseSimulation(
50 51
      _currentSimulation.x(time - _offset),
      _currentSimulation.dx(time - _offset), time);
52 53 54 55

  @override
  Simulation get currentSimulation => _currentSimulation;

56 57 58
  @override
  double get currentIntervalOffset => _offset;

59 60
  bool _chooseSimulation(double position, double velocity, double intervalOffset) {
    if (_spring == null && (position > _trailingExtent || position < _leadingExtent))
61 62
      return false;

Ian Hickson's avatar
Ian Hickson committed
63
    // This simulation can only step forward.
64 65 66
    if (!_isSpringing) {
      if (position > _trailingExtent) {
        _isSpringing = true;
67
        _offset = intervalOffset;
68
        _currentSimulation = new ScrollSpringSimulation(_spring, position, _trailingExtent, velocity);
69
        return true;
70 71
      } else if (position < _leadingExtent) {
        _isSpringing = true;
72
        _offset = intervalOffset;
73
        _currentSimulation = new ScrollSpringSimulation(_spring, position, _leadingExtent, velocity);
74
        return true;
75
      }
76 77 78
    }

    if (_currentSimulation == null) {
79
      _currentSimulation = new FrictionSimulation(_drag, position, velocity);
80
      return true;
81
    }
82 83

    return false;
84
  }
85

86
  @override
87 88 89
  String toString() {
    return 'ScrollSimulation(leadingExtent: $_leadingExtent, trailingExtent: $_trailingExtent)';
  }
90
}