@@ -129,8 +129,6 @@ class BouncingScrollSimulation extends Simulation {
129129 }
130130}
131131
132- const double _inflexion = 0.35 ;
133-
134132/// An implementation of scroll physics that matches Android.
135133///
136134/// See also:
@@ -149,9 +147,10 @@ class ClampingScrollSimulation extends Simulation {
149147 required this .velocity,
150148 this .friction = 0.015 ,
151149 Tolerance tolerance = Tolerance .defaultTolerance,
152- }) : super (tolerance: tolerance) {
153- _duration = _splineFlingDuration (velocity);
154- _distance = _splineFlingDistance (velocity);
150+ }) : assert (_flingVelocityPenetration (0.0 ) == _initialVelocityPenetration),
151+ super (tolerance: tolerance) {
152+ _duration = _flingDuration (velocity);
153+ _distance = (velocity * _duration / _initialVelocityPenetration).abs ();
155154 }
156155
157156 /// The position of the particle at the beginning of the simulation.
@@ -166,192 +165,67 @@ class ClampingScrollSimulation extends Simulation {
166165 /// The more friction the particle experiences, the sooner it stops.
167166 final double friction;
168167
169- late int _duration;
168+ late double _duration;
170169 late double _distance;
171170
172171 // See DECELERATION_RATE.
173172 static final double _kDecelerationRate = math.log (0.78 ) / math.log (0.9 );
174173
175174 // See computeDeceleration().
176175 static double _decelerationForFriction (double friction) {
177- return 9.80665 *
178- 39.37 *
179- friction *
180- 1.0 * // Flutter operates on logical pixels so the DPI should be 1.0.
181- 160.0 ;
176+ return friction * 61774.04968 ;
182177 }
183178
184- // See getSplineDeceleration().
185- double _splineDeceleration (double velocity) {
186- return math.log (_inflexion * velocity.abs () / (friction * _decelerationForFriction (0.84 )));
179+ // See getSplineFlingDuration(). Returns a value in seconds.
180+ double _flingDuration (double velocity) {
181+ // See mPhysicalCoeff
182+ final double scaledFriction = friction * _decelerationForFriction (0.84 );
183+
184+ // See getSplineDeceleration().
185+ final double deceleration = math.log (0.35 * velocity.abs () / scaledFriction);
186+
187+ return math.exp (deceleration / (_kDecelerationRate - 1.0 ));
187188 }
188189
189- // See getSplineFlingDuration().
190- int _splineFlingDuration (double velocity) {
191- final double deceleration = _splineDeceleration (velocity);
192- return (1000 * math.exp (deceleration / (_kDecelerationRate - 1.0 ))).round ();
190+ // Based on a cubic curve fit to the Scroller.computeScrollOffset() values
191+ // produced for an initial velocity of 4000. The value of Scroller.getDuration()
192+ // and Scroller.getFinalY() were 686ms and 961 pixels respectively.
193+ //
194+ // Algebra courtesy of Wolfram Alpha.
195+ //
196+ // f(x) = scrollOffset, x is time in milliseconds
197+ // f(x) = 3.60882×10^-6 x^3 - 0.00668009 x^2 + 4.29427 x - 3.15307
198+ // f(x) = 3.60882×10^-6 x^3 - 0.00668009 x^2 + 4.29427 x, so f(0) is 0
199+ // f(686ms) = 961 pixels
200+ // Scale to f(0 <= t <= 1.0), x = t * 686
201+ // f(t) = 1165.03 t^3 - 3143.62 t^2 + 2945.87 t
202+ // Scale f(t) so that 0.0 <= f(t) <= 1.0
203+ // f(t) = (1165.03 t^3 - 3143.62 t^2 + 2945.87 t) / 961.0
204+ // = 1.2 t^3 - 3.27 t^2 + 3.065 t
205+ static const double _initialVelocityPenetration = 3.065 ;
206+ static double _flingDistancePenetration (double t) {
207+ return (1.2 * t * t * t) - (3.27 * t * t) + (_initialVelocityPenetration * t);
193208 }
194209
195- // See getSplineFlingDistance().
196- double _splineFlingDistance (double velocity) {
197- final double l = _splineDeceleration (velocity);
198- final double decelMinusOne = _kDecelerationRate - 1.0 ;
199- return friction *
200- _decelerationForFriction (0.84 ) *
201- math.exp (_kDecelerationRate / decelMinusOne * l);
210+ // The derivative of the _flingDistancePenetration() function.
211+ static double _flingVelocityPenetration (double t) {
212+ return (3.6 * t * t) - (6.54 * t) + _initialVelocityPenetration;
202213 }
203214
204215 @override
205216 double x (double time) {
206- if (time == 0 ) {
207- return position;
208- }
209- final _NBSample sample = _NBSample (time, _duration);
210- return position + (sample.distanceCoef * _distance) * velocity.sign;
217+ final double t = (time / _duration).clamp (0.0 , 1.0 );
218+ return position + _distance * _flingDistancePenetration (t) * velocity.sign;
211219 }
212220
213221 @override
214222 double dx (double time) {
215- if (time == 0 ) {
216- return velocity;
217- }
218- final _NBSample sample = _NBSample (time, _duration);
219- return sample.velocityCoef * _distance / _duration * velocity.sign * 1000.0 ;
223+ final double t = (time / _duration).clamp (0.0 , 1.0 );
224+ return _distance * _flingVelocityPenetration (t) * velocity.sign / _duration;
220225 }
221226
222227 @override
223228 bool isDone (double time) {
224- return time * 1000.0 >= _duration;
225- }
226- }
227-
228- class _NBSample {
229- _NBSample (double time, int duration) {
230- // See computeScrollOffset().
231- final double t = time * 1000.0 / duration;
232- final int index = (_nbSamples * t).clamp (0 , _nbSamples).round ();
233- _distanceCoef = 1.0 ;
234- _velocityCoef = 0.0 ;
235- if (index < _nbSamples) {
236- final double tInf = index / _nbSamples;
237- final double tSup = (index + 1 ) / _nbSamples;
238- final double dInf = _splinePosition[index];
239- final double dSup = _splinePosition[index + 1 ];
240- _velocityCoef = (dSup - dInf) / (tSup - tInf);
241- _distanceCoef = dInf + (t - tInf) * _velocityCoef;
242- }
229+ return time >= _duration;
243230 }
244-
245- late double _velocityCoef;
246- double get velocityCoef => _velocityCoef;
247-
248- late double _distanceCoef;
249- double get distanceCoef => _distanceCoef;
250-
251- static const int _nbSamples = 100 ;
252-
253- // Generated from dev/tools/generate_android_spline_data.dart.
254- static final List <double > _splinePosition = < double > [
255- 0.000022888183591973643 ,
256- 0.028561000304762274 ,
257- 0.05705195792956655 ,
258- 0.08538917797618413 ,
259- 0.11349556286812107 ,
260- 0.14129881694635613 ,
261- 0.16877157254923383 ,
262- 0.19581093511175632 ,
263- 0.22239649722992452 ,
264- 0.24843841866631658 ,
265- 0.2740024733220569 ,
266- 0.298967680744136 ,
267- 0.32333234658228116 ,
268- 0.34709556909569184 ,
269- 0.3702249257894571 ,
270- 0.39272483400399893 ,
271- 0.41456988647721615 ,
272- 0.43582889025419114 ,
273- 0.4564192786416 ,
274- 0.476410299013587 ,
275- 0.4957560715637827 ,
276- 0.5145493169954743 ,
277- 0.5327205670880077 ,
278- 0.5502846891191615 ,
279- 0.5673274324802855 ,
280- 0.583810881323224 ,
281- 0.5997478744397482 ,
282- 0.615194045299478 ,
283- 0.6301165005270208 ,
284- 0.6445484042257972 ,
285- 0.6585198219185201 ,
286- 0.6720397744233084 ,
287- 0.6850997688076114 ,
288- 0.6977281404741683 ,
289- 0.7099506591298411 ,
290- 0.7217749311525871 ,
291- 0.7331784038850426 ,
292- 0.7442308394229518 ,
293- 0.7549087205105974 ,
294- 0.7652471277371271 ,
295- 0.7752251637549381 ,
296- 0.7848768260203478 ,
297- 0.7942056937103814 ,
298- 0.8032299679689082 ,
299- 0.8119428702388629 ,
300- 0.8203713516576219 ,
301- 0.8285187880808974 ,
302- 0.8363794492831295 ,
303- 0.8439768562813565 ,
304- 0.851322799855549 ,
305- 0.8584111051351724 ,
306- 0.8652534074722162 ,
307- 0.8718525580962131 ,
308- 0.8782333271742155 ,
309- 0.8843892099362031 ,
310- 0.8903155590440985 ,
311- 0.8960465359221951 ,
312- 0.9015574505919048 ,
313- 0.9068736766459904 ,
314- 0.9119951682409297 ,
315- 0.9169321898723632 ,
316- 0.9216747065581234 ,
317- 0.9262420604674766 ,
318- 0.9306331858366086 ,
319- 0.9348476990715433 ,
320- 0.9389007110754832 ,
321- 0.9427903495057521 ,
322- 0.9465220679845756 ,
323- 0.9500943036519721 ,
324- 0.9535176728088761 ,
325- 0.9567898524767604 ,
326- 0.959924306623116 ,
327- 0.9629127700159108 ,
328- 0.9657622101750765 ,
329- 0.9684818726275105 ,
330- 0.9710676079044347 ,
331- 0.9735231939498 ,
332- 0.9758514437576309 ,
333- 0.9780599066560445 ,
334- 0.9801485715370128 ,
335- 0.9821149805689633 ,
336- 0.9839677526782791 ,
337- 0.9857085499421516 ,
338- 0.9873347811966005 ,
339- 0.9888547171706613 ,
340- 0.9902689443512227 ,
341- 0.9915771042095881 ,
342- 0.9927840651641069 ,
343- 0.9938913963715834 ,
344- 0.9948987305580712 ,
345- 0.9958114963810524 ,
346- 0.9966274782266875 ,
347- 0.997352148697352 ,
348- 0.9979848677523623 ,
349- 0.9985285021374979 ,
350- 0.9989844084453229 ,
351- 0.9993537595844986 ,
352- 0.999638729860106 ,
353- 0.9998403888004533 ,
354- 0.9999602810470701 ,
355- 1.0 ,
356- ];
357231}
0 commit comments