Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
4ca447b6
Commit
4ca447b6
authored
May 03, 2017
by
Hans Muller
Committed by
GitHub
May 03, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored the iOS Scrolling Simulation (#9754)
parent
46105468
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
158 additions
and
134 deletions
+158
-134
physics.dart
packages/flutter/lib/physics.dart
+0
-1
friction_simulation.dart
packages/flutter/lib/src/physics/friction_simulation.dart
+14
-0
simulation_group.dart
packages/flutter/lib/src/physics/simulation_group.dart
+0
-78
scroll_simulation.dart
packages/flutter/lib/src/widgets/scroll_simulation.dart
+70
-48
friction_simulation_test.dart
packages/flutter/test/physics/friction_simulation_test.dart
+52
-0
newton_test.dart
packages/flutter/test/physics/newton_test.dart
+22
-7
No files found.
packages/flutter/lib/physics.dart
View file @
4ca447b6
...
...
@@ -12,7 +12,6 @@ export 'src/physics/clamped_simulation.dart';
export
'src/physics/friction_simulation.dart'
;
export
'src/physics/gravity_simulation.dart'
;
export
'src/physics/simulation.dart'
;
export
'src/physics/simulation_group.dart'
;
export
'src/physics/spring_simulation.dart'
;
export
'src/physics/tolerance.dart'
;
export
'src/physics/utils.dart'
;
packages/flutter/lib/src/physics/friction_simulation.dart
View file @
4ca447b6
...
...
@@ -71,6 +71,20 @@ class FrictionSimulation extends Simulation {
@override
double
dx
(
double
time
)
=>
_v
*
math
.
pow
(
_drag
,
time
);
/// The value of [x] at `double.INFINITY`.
double
get
finalX
=>
_x
-
_v
/
_dragLog
;
/// The time at which the value of `x(time)` will equal [x].
///
/// Returns `double.INFINITY` if the simulation will never reach [x].
double
timeAtX
(
double
x
)
{
if
(
x
==
_x
)
return
0.0
;
if
(
_v
==
0.0
||
(
_v
>
0
?
(
x
<
_x
||
x
>
finalX
)
:
(
x
>
_x
||
x
<
finalX
)))
return
double
.
INFINITY
;
return
math
.
log
(
_dragLog
*
(
x
-
_x
)
/
_v
+
1.0
)
/
_dragLog
;
}
@override
bool
isDone
(
double
time
)
=>
dx
(
time
).
abs
()
<
tolerance
.
velocity
;
}
...
...
packages/flutter/lib/src/physics/simulation_group.dart
deleted
100644 → 0
View file @
46105468
// Copyright 2016 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
'simulation.dart'
;
import
'tolerance.dart'
;
import
'utils.dart'
;
/// Base class for composite simulations.
///
/// Concrete subclasses must implement the [currentSimulation] getter, the
/// [currentIntervalOffset] getter, and the [step] function to select the
/// appropriate simulation at a given time interval. This class implements the
/// [x], [dx], and [isDone] functions by calling the [step] method if necessary
/// and then deferring to the [currentSimulation]'s methods with a time offset
/// by [currentIntervalOffset].
///
/// The tolerance of this simulation is pushed to the simulations that are used
/// by this group as they become active. This mean simulations should not be
/// shared among different groups that are active at the same time.
abstract
class
SimulationGroup
extends
Simulation
{
/// Initializes the [tolerance] field for subclasses.
SimulationGroup
({
Tolerance
tolerance:
Tolerance
.
defaultTolerance
})
:
super
(
tolerance:
tolerance
);
/// The currently active simulation.
///
/// This getter should return the same value until [step] is called and
/// returns true.
Simulation
get
currentSimulation
;
/// The time offset applied to the currently active simulation when deferring
/// [x], [dx], and [isDone] to it.
double
get
currentIntervalOffset
;
/// Called when a significant change in the interval is detected. Subclasses
/// must decide if the current simulation must be switched (or updated).
///
/// Must return true if the simulation was switched in this step, otherwise
/// false.
///
/// If this function returns true, then [currentSimulation] must start
/// returning a new value.
bool
step
(
double
time
);
double
_lastStep
=
-
1.0
;
void
_stepIfNecessary
(
double
time
)
{
if
(
nearEqual
(
_lastStep
,
time
,
Tolerance
.
defaultTolerance
.
time
))
return
;
_lastStep
=
time
;
if
(
step
(
time
))
currentSimulation
.
tolerance
=
tolerance
;
}
@override
double
x
(
double
time
)
{
_stepIfNecessary
(
time
);
return
currentSimulation
.
x
(
time
-
currentIntervalOffset
);
}
@override
double
dx
(
double
time
)
{
_stepIfNecessary
(
time
);
return
currentSimulation
.
dx
(
time
-
currentIntervalOffset
);
}
@override
bool
isDone
(
double
time
)
{
_stepIfNecessary
(
time
);
return
currentSimulation
.
isDone
(
time
-
currentIntervalOffset
);
}
@override
set
tolerance
(
Tolerance
value
)
{
currentSimulation
.
tolerance
=
value
;
super
.
tolerance
=
value
;
}
}
packages/flutter/lib/src/widgets/scroll_simulation.dart
View file @
4ca447b6
...
...
@@ -12,7 +12,7 @@ import 'package:flutter/physics.dart';
/// See also:
///
/// * [ClampingScrollSimulation], which implements Android scroll physics.
class
BouncingScrollSimulation
extends
Simulation
Group
{
class
BouncingScrollSimulation
extends
Simulation
{
/// Creates a simulation group for scrolling on iOS, with the given
/// parameters.
///
...
...
@@ -31,68 +31,90 @@ class BouncingScrollSimulation extends SimulationGroup {
BouncingScrollSimulation
({
@required
double
position
,
@required
double
velocity
,
@required
double
leadingExtent
,
@required
double
trailingExtent
,
@required
SpringDescription
spring
,
@required
this
.
leadingExtent
,
@required
this
.
trailingExtent
,
@required
this
.
spring
,
Tolerance
tolerance:
Tolerance
.
defaultTolerance
,
})
:
_leadingExtent
=
leadingExtent
,
_trailingExtent
=
trailingExtent
,
_spring
=
spring
,
super
(
tolerance:
tolerance
)
{
})
:
super
(
tolerance:
tolerance
)
{
assert
(
position
!=
null
);
assert
(
velocity
!=
null
);
assert
(
_leadingExtent
!=
null
);
assert
(
_trailingExtent
!=
null
);
assert
(
_leadingExtent
<=
_trailingExtent
);
assert
(
_spring
!=
null
);
_chooseSimulation
(
position
,
velocity
,
0.0
);
assert
(
leadingExtent
!=
null
);
assert
(
trailingExtent
!=
null
);
assert
(
leadingExtent
<=
trailingExtent
);
assert
(
spring
!=
null
);
if
(
position
<
leadingExtent
)
{
_springSimulation
=
_underscrollSimulation
(
position
,
velocity
);
_springTime
=
double
.
NEGATIVE_INFINITY
;
}
else
if
(
position
>
trailingExtent
)
{
_springSimulation
=
_overscrollSimulation
(
position
,
velocity
);
_springTime
=
double
.
NEGATIVE_INFINITY
;
}
else
{
_frictionSimulation
=
new
FrictionSimulation
(
0.135
,
position
,
velocity
);
final
double
finalX
=
_frictionSimulation
.
finalX
;
if
(
velocity
>
0.0
&&
finalX
>
trailingExtent
)
{
_springTime
=
_frictionSimulation
.
timeAtX
(
trailingExtent
);
_springSimulation
=
_overscrollSimulation
(
trailingExtent
,
_frictionSimulation
.
dx
(
_springTime
));
assert
(
_springTime
.
isFinite
);
}
else
if
(
velocity
<
0.0
&&
finalX
<
leadingExtent
)
{
_springTime
=
_frictionSimulation
.
timeAtX
(
leadingExtent
);
_springSimulation
=
_underscrollSimulation
(
leadingExtent
,
_frictionSimulation
.
dx
(
_springTime
));
assert
(
_springTime
.
isFinite
);
}
else
{
_springTime
=
double
.
INFINITY
;
}
}
assert
(
_springTime
!=
null
);
}
final
double
_leadingExtent
;
final
double
_trailingExtent
;
final
SpringDescription
_spring
;
/// When [x] falls below this value the simulation switches from an internal friction
/// model to a spring model which causes [x] to "spring" back to [leadingExtent].
final
double
leadingExtent
;
/// When [x] exceeds this value the simulation switches from an internal friction
/// model to a spring model which causes [x] to "spring" back to [trailingExtent].
final
double
trailingExtent
;
bool
_isSpringing
=
false
;
Simulation
_currentSimulation
;
double
_offset
=
0.0
;
/// The spring used used to return [x] to either [leadingExtent] or [trailingExtent].
final
SpringDescription
spring
;
FrictionSimulation
_frictionSimulation
;
Simulation
_springSimulation
;
double
_springTime
;
double
_timeOffset
=
0.0
;
Simulation
_underscrollSimulation
(
double
x
,
double
dx
)
{
return
new
ScrollSpringSimulation
(
spring
,
x
,
leadingExtent
,
dx
);
}
Simulation
_overscrollSimulation
(
double
x
,
double
dx
)
{
return
new
ScrollSpringSimulation
(
spring
,
x
,
trailingExtent
,
dx
);
}
Simulation
_simulation
(
double
time
)
{
Simulation
simulation
;
if
(
time
>
_springTime
)
{
_timeOffset
=
_springTime
.
isFinite
?
_springTime
:
0.0
;
simulation
=
_springSimulation
;
}
else
{
_timeOffset
=
0.0
;
simulation
=
_frictionSimulation
;
}
return
simulation
..
tolerance
=
tolerance
;
}
// This simulation can only step forward.
@override
bool
step
(
double
time
)
=>
_chooseSimulation
(
_currentSimulation
.
x
(
time
-
_offset
),
_currentSimulation
.
dx
(
time
-
_offset
),
time
,
);
double
x
(
double
time
)
=>
_simulation
(
time
).
x
(
time
-
_timeOffset
);
@override
Simulation
get
currentSimulation
=>
_currentSimulation
;
double
dx
(
double
time
)
=>
_simulation
(
time
).
dx
(
time
-
_timeOffset
)
;
@override
double
get
currentIntervalOffset
=>
_offset
;
bool
_chooseSimulation
(
double
position
,
double
velocity
,
double
intervalOffset
)
{
if
(!
_isSpringing
)
{
if
(
position
>
_trailingExtent
)
{
_isSpringing
=
true
;
_offset
=
intervalOffset
;
_currentSimulation
=
new
ScrollSpringSimulation
(
_spring
,
position
,
_trailingExtent
,
velocity
,
tolerance:
tolerance
);
return
true
;
}
else
if
(
position
<
_leadingExtent
)
{
_isSpringing
=
true
;
_offset
=
intervalOffset
;
_currentSimulation
=
new
ScrollSpringSimulation
(
_spring
,
position
,
_leadingExtent
,
velocity
,
tolerance:
tolerance
);
return
true
;
}
else
if
(
_currentSimulation
==
null
)
{
_currentSimulation
=
new
FrictionSimulation
(
0.135
,
position
,
velocity
,
tolerance:
tolerance
);
return
true
;
}
}
return
false
;
}
bool
isDone
(
double
time
)
=>
_simulation
(
time
).
isDone
(
time
-
_timeOffset
);
@override
String
toString
()
{
return
'
$runtimeType
(leadingExtent:
$
_leadingExtent
, trailingExtent:
$_
trailingExtent
)'
;
return
'
$runtimeType
(leadingExtent:
$
leadingExtent
, trailingExtent:
$
trailingExtent
)'
;
}
}
...
...
packages/flutter/test/physics/friction_simulation_test.dart
0 → 100644
View file @
4ca447b6
// Copyright 2017 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
'package:flutter/physics.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
const
double
_kEpsilon
=
.
00001
;
void
main
(
)
{
test
(
'Friction simulation positive velocity'
,
()
{
final
FrictionSimulation
friction
=
new
FrictionSimulation
(
0.135
,
100.0
,
100.0
);
expect
(
friction
.
x
(
0.0
),
closeTo
(
100.0
,
_kEpsilon
));
expect
(
friction
.
dx
(
0.0
),
closeTo
(
100.0
,
_kEpsilon
));
expect
(
friction
.
x
(
0.1
),
closeTo
(
110.0
,
1.0
));
expect
(
friction
.
x
(
0.5
),
closeTo
(
131.0
,
1.0
));
expect
(
friction
.
x
(
2.0
),
closeTo
(
149.0
,
1.0
));
expect
(
friction
.
finalX
,
closeTo
(
149.0
,
1.0
));
expect
(
friction
.
timeAtX
(
100.0
),
0.0
);
expect
(
friction
.
timeAtX
(
friction
.
x
(
0.1
)),
closeTo
(
0.1
,
_kEpsilon
));
expect
(
friction
.
timeAtX
(
friction
.
x
(
0.5
)),
closeTo
(
0.5
,
_kEpsilon
));
expect
(
friction
.
timeAtX
(
friction
.
x
(
2.0
)),
closeTo
(
2.0
,
_kEpsilon
));
expect
(
friction
.
timeAtX
(-
1.0
),
double
.
INFINITY
);
expect
(
friction
.
timeAtX
(
200.0
),
double
.
INFINITY
);
});
test
(
'Friction simulation negative velocity'
,
()
{
final
FrictionSimulation
friction
=
new
FrictionSimulation
(
0.135
,
100.0
,
-
100.0
);
expect
(
friction
.
x
(
0.0
),
closeTo
(
100.0
,
_kEpsilon
));
expect
(
friction
.
dx
(
0.0
),
closeTo
(-
100.0
,
_kEpsilon
));
expect
(
friction
.
x
(
0.1
),
closeTo
(
91.0
,
1.0
));
expect
(
friction
.
x
(
0.5
),
closeTo
(
68.0
,
1.0
));
expect
(
friction
.
x
(
2.0
),
closeTo
(
51.0
,
1.0
));
expect
(
friction
.
finalX
,
closeTo
(
50
,
1.0
));
expect
(
friction
.
timeAtX
(
100.0
),
0.0
);
expect
(
friction
.
timeAtX
(
friction
.
x
(
0.1
)),
closeTo
(
0.1
,
_kEpsilon
));
expect
(
friction
.
timeAtX
(
friction
.
x
(
0.5
)),
closeTo
(
0.5
,
_kEpsilon
));
expect
(
friction
.
timeAtX
(
friction
.
x
(
2.0
)),
closeTo
(
2.0
,
_kEpsilon
));
expect
(
friction
.
timeAtX
(
101.0
),
double
.
INFINITY
);
expect
(
friction
.
timeAtX
(
40.0
),
double
.
INFINITY
);
});
}
packages/flutter/test/physics/newton_test.dart
View file @
4ca447b6
...
...
@@ -256,9 +256,6 @@ void main() {
expect
(
scroll
.
isDone
(
5.0
),
true
);
expect
(
scroll
.
x
(
5.0
),
closeTo
(
300.0
,
1.0
));
// We should never switch
expect
(
scroll
.
currentIntervalOffset
,
0.0
);
});
test
(
'over/under scroll spring'
,
()
{
...
...
@@ -276,12 +273,30 @@ void main() {
expect
(
scroll
.
x
(
0.0
),
closeTo
(
500.0
,
.
0001
));
expect
(
scroll
.
dx
(
0.0
),
closeTo
(-
7500.0
,
.
0001
));
expect
(
scroll
.
isDone
(
0.025
),
false
);
expect
(
scroll
.
x
(
0.025
),
closeTo
(
317.0
,
1.0
));
expect
(
scroll
.
dx
(
0.25
),
closeTo
(-
4546
,
1.0
));
// Expect to reach 0.0 at about t=.07 at which point the simulation will
// switch from friction to the spring
expect
(
scroll
.
isDone
(
0.065
),
false
);
expect
(
scroll
.
x
(
0.065
),
closeTo
(
42.0
,
1.0
));
expect
(
scroll
.
dx
(
0.065
),
closeTo
(-
6584.0
,
1.0
));
// We've overscrolled (0.1 > 0.07). Trigger the underscroll
// simulation, and reverse direction
expect
(
scroll
.
isDone
(
0.1
),
false
);
expect
(
scroll
.
x
(
0.1
),
closeTo
(-
123.0
,
1.0
));
expect
(
scroll
.
dx
(
0.1
),
closeTo
(-
2613.0
,
1.0
));
// Headed back towards 0.0 and slowing down.
expect
(
scroll
.
isDone
(
0.5
),
false
);
expect
(
scroll
.
x
(
0.5
),
closeTo
(-
15.0
,
1.0
));
expect
(
scroll
.
dx
(
0.5
),
closeTo
(
124.0
,
1.0
));
// Now jump back to the beginning, because we can.
expect
(
scroll
.
isDone
(
0.0
),
false
);
expect
(
scroll
.
x
(
0.0
),
closeTo
(
500.0
,
.
0001
));
expect
(
scroll
.
dx
(
0.0
),
closeTo
(-
7500.0
,
.
0001
));
expect
(
scroll
.
isDone
(
2.0
),
true
);
expect
(
scroll
.
x
(
2.0
),
0.0
);
expect
(
scroll
.
dx
(
2.0
),
closeTo
(
0.0
,
45
.0
));
expect
(
scroll
.
dx
(
2.0
),
closeTo
(
0.0
,
1
.0
));
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment