提交 85d02799 编写于 作者: A Adam Barth

Improve Sky's Scrollable physics

We now use a physics simulationt to drive the scroll fling. We're also closer
to integrating fling into overscroll.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/1004363002
上级 0765e85b
......@@ -5,7 +5,7 @@
import 'dart:math' as math;
const double kGravity = -0.980;
const double _kMinVelocity = 0.1;
const double _kMinVelocity = 0.01;
abstract class System {
void update(double deltaT);
......@@ -69,6 +69,23 @@ class ParticleInBox extends System {
}
}
class ParticleInBoxWithFriction extends ParticleInBox {
final double friction;
final double _sign;
ParticleInBoxWithFriction({Particle particle, Box box, this.friction})
: super(particle: particle, box: box),
_sign = particle.velocity.sign;
void update(double deltaT) {
double force = -_sign * friction;
particle.applyImpluse(force * deltaT);
if (particle.velocity.sign != _sign)
particle.velocity = 0.0;
super.update(deltaT);
}
}
class Spring {
final double k;
double displacement;
......
......@@ -6,7 +6,8 @@ import 'dart:math' as math;
import 'mechanics.dart';
import 'generators.dart';
const double _kSlope = 0.01;
const double _kSlope = 0.02;
const double _kFriction = 0.004;
abstract class ScrollBehavior {
Simulation release(Particle particle) => null;
......@@ -33,8 +34,16 @@ class BoundedScrollBehavior extends ScrollBehavior {
class OverscrollBehavior extends ScrollBehavior {
Simulation release(Particle particle) {
if (particle.position >= 0.0)
return null;
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),
......
......@@ -66,7 +66,7 @@ abstract class FixedHeightScrollable extends Scrollable {
alignmentDelta -= _itemHeight;
double drawStart = scrollOffset + alignmentDelta;
itemNumber = (drawStart / _itemHeight).floor();
itemNumber = math.max(0, (drawStart / _itemHeight).floor());
transformStyle =
'transform: translateY(${(alignmentDelta).toStringAsFixed(2)}px)';
......
......@@ -2,21 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../animation/curves.dart';
import '../animation/fling_curve.dart';
import '../animation/generators.dart';
import '../animation/scroll_behavior.dart';
import '../animation/mechanics.dart';
import '../animation/scroll_behavior.dart';
import '../fn.dart';
import '../theme/view-configuration.dart' as config;
import 'dart:math' as math;
import 'dart:sky' as sky;
const double _kMillisecondsPerSecond = 1000.0;
double _velocityForFlingGesture(sky.GestureEvent event) {
return math.max(-config.kMaxFlingVelocity, math.min(config.kMaxFlingVelocity,
-event.velocityY)) / _kMillisecondsPerSecond;
}
abstract class Scrollable extends Component {
ScrollBehavior scrollBehavior;
double get scrollOffset => _scrollOffset;
double _scrollOffset = 0.0;
FlingCurve _flingCurve;
int _flingAnimationId;
Simulation _simulation;
Scrollable({Object key, this.scrollBehavior}) : super(key: key) {
......@@ -31,7 +36,6 @@ abstract class Scrollable extends Component {
void didUnmount() {
super.didUnmount();
_stopFling();
_stopSimulation();
}
......@@ -45,18 +49,6 @@ abstract class Scrollable extends Component {
return true;
}
void _scheduleFlingUpdate() {
_flingAnimationId = sky.window.requestAnimationFrame(_updateFling);
}
void _stopFling() {
if (_flingAnimationId == null)
return;
sky.window.cancelAnimationFrame(_flingAnimationId);
_flingCurve = null;
_flingAnimationId = null;
}
void _stopSimulation() {
if (_simulation == null)
return;
......@@ -64,16 +56,8 @@ abstract class Scrollable extends Component {
_simulation = null;
}
void _updateFling(double timeStamp) {
double scrollDelta = _flingCurve.update(timeStamp);
if (!scrollBy(scrollDelta))
return _settle();
_scheduleFlingUpdate();
}
void _settle() {
_stopFling();
Particle particle = new Particle(position: scrollOffset);
void _startSimulation(Particle particle) {
_stopSimulation();
_simulation = scrollBehavior.release(particle);
if (_simulation == null)
return;
......@@ -84,14 +68,17 @@ abstract class Scrollable extends Component {
});
}
Particle _createParticle([double velocity = 0.0]) {
return new Particle(position: _scrollOffset, velocity: velocity);
}
void _handlePointerDown(_) {
_stopFling();
_stopSimulation();
}
void _handlePointerUpOrCancel(_) {
if (_flingCurve == null)
_settle();
if (_simulation == null)
_startSimulation(_createParticle());
}
void _handleScrollUpdate(sky.GestureEvent event) {
......@@ -99,13 +86,11 @@ abstract class Scrollable extends Component {
}
void _handleFlingStart(sky.GestureEvent event) {
_stopSimulation();
_flingCurve = new FlingCurve(-event.velocityY, event.timeStamp);
_scheduleFlingUpdate();
_startSimulation(_createParticle(_velocityForFlingGesture(event)));
}
void _handleFlingCancel(sky.GestureEvent event) {
_settle();
_startSimulation(_createParticle());
}
void _handleWheel(sky.WheelEvent event) {
......
......@@ -5,6 +5,8 @@
// Modeled after Android's ViewConfiguration:
// https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/ViewConfiguration.java
const int kScrollbarSize = 10;
const int kMaxFlingVelocity = 8000;
const int kMinFlingVelocity = 50;
const int kScrollbarFadeDelay = 300;
const int kScrollbarFadeDuration = 250;
const int kScrollbarSize = 10;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册