OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Implementations can be used to simulate the deceleration of an element within | 6 * Implementations can be used to simulate the deceleration of an element within |
7 * a certain region. To use this behavior you need to provide an initial | 7 * a certain region. To use this behavior you need to provide an initial |
8 * velocity that is meant to represent the gesture that is initiating this | 8 * velocity that is meant to represent the gesture that is initiating this |
9 * deceleration. You also provide the bounds of the region that the element | 9 * deceleration. You also provide the bounds of the region that the element |
10 * exists in, and the current offset of the element within that region. The | 10 * exists in, and the current offset of the element within that region. The |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 | 271 |
272 /** | 272 /** |
273 * Helper method to calculate initial velocity. | 273 * Helper method to calculate initial velocity. |
274 * The [velocity] passed here should be in terms of number of | 274 * The [velocity] passed here should be in terms of number of |
275 * pixels / millisecond. Returns the adjusted x and y velocities. | 275 * pixels / millisecond. Returns the adjusted x and y velocities. |
276 */ | 276 */ |
277 void _adjustInitialVelocityAndBouncingState(num v) { | 277 void _adjustInitialVelocityAndBouncingState(num v) { |
278 velocity = v * _MS_PER_FRAME * _INITIAL_VELOCITY_BOOST_FACTOR; | 278 velocity = v * _MS_PER_FRAME * _INITIAL_VELOCITY_BOOST_FACTOR; |
279 | 279 |
280 if (velocity.abs() < _MIN_VELOCITY) { | 280 if (velocity.abs() < _MIN_VELOCITY) { |
281 if (_minCoord !== null && _currentOffset < _minCoord) { | 281 if (_minCoord != null && _currentOffset < _minCoord) { |
282 velocity = (_minCoord - _currentOffset) * _POST_BOUNCE_COEFFICIENT; | 282 velocity = (_minCoord - _currentOffset) * _POST_BOUNCE_COEFFICIENT; |
283 velocity = Math.max(velocity, _MIN_STEP_VELOCITY); | 283 velocity = Math.max(velocity, _MIN_STEP_VELOCITY); |
284 _bouncingState = BouncingState.BOUNCING_BACK; | 284 _bouncingState = BouncingState.BOUNCING_BACK; |
285 } else if (_maxCoord !== null && _currentOffset > _maxCoord) { | 285 } else if (_maxCoord != null && _currentOffset > _maxCoord) { |
286 velocity = (_currentOffset - _maxCoord) * _POST_BOUNCE_COEFFICIENT; | 286 velocity = (_currentOffset - _maxCoord) * _POST_BOUNCE_COEFFICIENT; |
287 velocity = -Math.max(velocity, _MIN_STEP_VELOCITY); | 287 velocity = -Math.max(velocity, _MIN_STEP_VELOCITY); |
288 _bouncingState = BouncingState.BOUNCING_BACK; | 288 _bouncingState = BouncingState.BOUNCING_BACK; |
289 } | 289 } |
290 } | 290 } |
291 } | 291 } |
292 | 292 |
293 /** | 293 /** |
294 * Apply deceleration. | 294 * Apply deceleration. |
295 */ | 295 */ |
296 void _adjustVelocity() { | 296 void _adjustVelocity() { |
297 num speed = velocity.abs(); | 297 num speed = velocity.abs(); |
298 velocity *= _DECELERATION_FACTOR; | 298 velocity *= _DECELERATION_FACTOR; |
299 if (customDecelerationFactor != null) { | 299 if (customDecelerationFactor != null) { |
300 velocity *= customDecelerationFactor; | 300 velocity *= customDecelerationFactor; |
301 } | 301 } |
302 // This isn't really how static friction works but it is a plausible | 302 // This isn't really how static friction works but it is a plausible |
303 // approximation. | 303 // approximation. |
304 if (speed < _MAX_VELOCITY_STATIC_FRICTION) { | 304 if (speed < _MAX_VELOCITY_STATIC_FRICTION) { |
305 velocity *= _DECELERATION_FACTOR_STATIC_FRICTION; | 305 velocity *= _DECELERATION_FACTOR_STATIC_FRICTION; |
306 } | 306 } |
307 | 307 |
308 num stretchDistance; | 308 num stretchDistance; |
309 if (_minCoord !== null && _currentOffset < _minCoord) { | 309 if (_minCoord != null && _currentOffset < _minCoord) { |
310 stretchDistance = _minCoord - _currentOffset; | 310 stretchDistance = _minCoord - _currentOffset; |
311 } else { | 311 } else { |
312 if (_maxCoord !== null && _currentOffset > _maxCoord) { | 312 if (_maxCoord != null && _currentOffset > _maxCoord) { |
313 stretchDistance = _maxCoord - _currentOffset; | 313 stretchDistance = _maxCoord - _currentOffset; |
314 } | 314 } |
315 } | 315 } |
316 if (stretchDistance != null) { | 316 if (stretchDistance != null) { |
317 if (stretchDistance * velocity < 0) { | 317 if (stretchDistance * velocity < 0) { |
318 _bouncingState = _bouncingState == BouncingState.BOUNCING_BACK ? | 318 _bouncingState = _bouncingState == BouncingState.BOUNCING_BACK ? |
319 BouncingState.NOT_BOUNCING : BouncingState.BOUNCING_AWAY; | 319 BouncingState.NOT_BOUNCING : BouncingState.BOUNCING_AWAY; |
320 velocity += stretchDistance * _PRE_BOUNCE_COEFFICIENT; | 320 velocity += stretchDistance * _PRE_BOUNCE_COEFFICIENT; |
321 } else { | 321 } else { |
322 _bouncingState = BouncingState.BOUNCING_BACK; | 322 _bouncingState = BouncingState.BOUNCING_BACK; |
323 velocity = stretchDistance > 0 ? | 323 velocity = stretchDistance > 0 ? |
324 Math.max(stretchDistance * _POST_BOUNCE_COEFFICIENT, | 324 Math.max(stretchDistance * _POST_BOUNCE_COEFFICIENT, |
325 _MIN_STEP_VELOCITY) : | 325 _MIN_STEP_VELOCITY) : |
326 Math.min(stretchDistance * _POST_BOUNCE_COEFFICIENT, | 326 Math.min(stretchDistance * _POST_BOUNCE_COEFFICIENT, |
327 -_MIN_STEP_VELOCITY); | 327 -_MIN_STEP_VELOCITY); |
328 } | 328 } |
329 } else { | 329 } else { |
330 _bouncingState = BouncingState.NOT_BOUNCING; | 330 _bouncingState = BouncingState.NOT_BOUNCING; |
331 } | 331 } |
332 } | 332 } |
333 | 333 |
334 void step() { | 334 void step() { |
335 // It is common for scrolling to be disabled so in these cases we want to | 335 // It is common for scrolling to be disabled so in these cases we want to |
336 // avoid needless calculations. | 336 // avoid needless calculations. |
337 if (velocity !== null) { | 337 if (velocity != null) { |
338 _currentOffset += velocity; | 338 _currentOffset += velocity; |
339 _adjustVelocity(); | 339 _adjustVelocity(); |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 void stepAll() { | 343 void stepAll() { |
344 while(!isDone()) { | 344 while(!isDone()) { |
345 step(); | 345 step(); |
346 } | 346 } |
347 } | 347 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 Coordinate calculateVelocity(Coordinate start_, Coordinate target, | 429 Coordinate calculateVelocity(Coordinate start_, Coordinate target, |
430 [num decelerationFactor = null]) { | 430 [num decelerationFactor = null]) { |
431 return new Coordinate( | 431 return new Coordinate( |
432 physicsX.solve(start_.x, target.x, decelerationFactor), | 432 physicsX.solve(start_.x, target.x, decelerationFactor), |
433 physicsY.solve(start_.y, target.y, decelerationFactor)); | 433 physicsY.solve(start_.y, target.y, decelerationFactor)); |
434 } | 434 } |
435 | 435 |
436 bool start(Coordinate velocity, Coordinate minCoord, Coordinate maxCoord, | 436 bool start(Coordinate velocity, Coordinate minCoord, Coordinate maxCoord, |
437 Coordinate initialOffset, [num decelerationFactor = null]) { | 437 Coordinate initialOffset, [num decelerationFactor = null]) { |
438 _customDecelerationFactor = _defaultDecelerationFactor; | 438 _customDecelerationFactor = _defaultDecelerationFactor; |
439 if (decelerationFactor !== null) { | 439 if (decelerationFactor != null) { |
440 _customDecelerationFactor = decelerationFactor; | 440 _customDecelerationFactor = decelerationFactor; |
441 } | 441 } |
442 | 442 |
443 if (_stepTimeout !== null) { | 443 if (_stepTimeout != null) { |
444 Env.cancelRequestAnimationFrame(_stepTimeout); | 444 Env.cancelRequestAnimationFrame(_stepTimeout); |
445 _stepTimeout = null; | 445 _stepTimeout = null; |
446 } | 446 } |
447 | 447 |
448 assert (_stepTimeout === null); | 448 assert (_stepTimeout == null); |
449 assert(minCoord.x <= maxCoord.x); | 449 assert(minCoord.x <= maxCoord.x); |
450 assert(minCoord.y <= maxCoord.y); | 450 assert(minCoord.y <= maxCoord.y); |
451 _previousOffset = initialOffset.clone(); | 451 _previousOffset = initialOffset.clone(); |
452 physicsX.configure(minCoord.x, maxCoord.x, initialOffset.x, | 452 physicsX.configure(minCoord.x, maxCoord.x, initialOffset.x, |
453 _customDecelerationFactor, velocity.x); | 453 _customDecelerationFactor, velocity.x); |
454 physicsY.configure(minCoord.y, maxCoord.y, initialOffset.y, | 454 physicsY.configure(minCoord.y, maxCoord.y, initialOffset.y, |
455 _customDecelerationFactor, velocity.y); | 455 _customDecelerationFactor, velocity.y); |
456 if (!physicsX.isDone() || !physicsY.isDone()) { | 456 if (!physicsX.isDone() || !physicsY.isDone()) { |
457 _calculateMoves(); | 457 _calculateMoves(); |
458 if (!_moves.isEmpty) { | 458 if (!_moves.isEmpty) { |
(...skipping 24 matching lines...) Expand all Loading... |
483 | 483 |
484 /** | 484 /** |
485 * Calculate the next offset of the element and animate it to that position. | 485 * Calculate the next offset of the element and animate it to that position. |
486 */ | 486 */ |
487 void _step(num timestamp) { | 487 void _step(num timestamp) { |
488 _stepTimeout = null; | 488 _stepTimeout = null; |
489 | 489 |
490 // Prune moves that are more than 1 frame behind when we have more | 490 // Prune moves that are more than 1 frame behind when we have more |
491 // available moves. | 491 // available moves. |
492 num lastEpoch = timestamp - SingleDimensionPhysics._MS_PER_FRAME; | 492 num lastEpoch = timestamp - SingleDimensionPhysics._MS_PER_FRAME; |
493 while (!_moves.isEmpty && _moves.first !== _moves.last | 493 while (!_moves.isEmpty && !identical(_moves.first, _moves.last) |
494 && _moves.first.time < lastEpoch) { | 494 && _moves.first.time < lastEpoch) { |
495 _moves.removeFirst(); | 495 _moves.removeFirst(); |
496 } | 496 } |
497 | 497 |
498 if (!_moves.isEmpty) { | 498 if (!_moves.isEmpty) { |
499 final move = _moves.removeFirst(); | 499 final move = _moves.removeFirst(); |
500 _delegate.onDecelerate(move.x, move.y); | 500 _delegate.onDecelerate(move.x, move.y); |
501 if (!_moves.isEmpty) { | 501 if (!_moves.isEmpty) { |
502 num nextTime = _moves.first.time; | 502 num nextTime = _moves.first.time; |
503 assert(_stepTimeout === null); | 503 assert(_stepTimeout == null); |
504 _stepTimeout = Env.requestAnimationFrame(_step, null, nextTime); | 504 _stepTimeout = Env.requestAnimationFrame(_step, null, nextTime); |
505 } else { | 505 } else { |
506 stop(); | 506 stop(); |
507 } | 507 } |
508 } | 508 } |
509 } | 509 } |
510 | 510 |
511 void abort() { | 511 void abort() { |
512 _decelerating = false; | 512 _decelerating = false; |
513 _moves.clear(); | 513 _moves.clear(); |
514 if (_stepTimeout !== null) { | 514 if (_stepTimeout != null) { |
515 Env.cancelRequestAnimationFrame(_stepTimeout); | 515 Env.cancelRequestAnimationFrame(_stepTimeout); |
516 _stepTimeout = null; | 516 _stepTimeout = null; |
517 } | 517 } |
518 } | 518 } |
519 | 519 |
520 Coordinate stop() { | 520 Coordinate stop() { |
521 final wasDecelerating = _decelerating; | 521 final wasDecelerating = _decelerating; |
522 _decelerating = false; | 522 _decelerating = false; |
523 Coordinate velocity; | 523 Coordinate velocity; |
524 if (!_moves.isEmpty) { | 524 if (!_moves.isEmpty) { |
525 final move = _moves.first; | 525 final move = _moves.first; |
526 // This is a workaround for the ugly hacks that get applied when a user | 526 // This is a workaround for the ugly hacks that get applied when a user |
527 // passed a velocity in to this Momentum implementation. | 527 // passed a velocity in to this Momentum implementation. |
528 num velocityScale = SingleDimensionPhysics._MS_PER_FRAME * | 528 num velocityScale = SingleDimensionPhysics._MS_PER_FRAME * |
529 SingleDimensionPhysics._INITIAL_VELOCITY_BOOST_FACTOR; | 529 SingleDimensionPhysics._INITIAL_VELOCITY_BOOST_FACTOR; |
530 velocity = new Coordinate( | 530 velocity = new Coordinate( |
531 move.vx / velocityScale, move.vy / velocityScale); | 531 move.vx / velocityScale, move.vy / velocityScale); |
532 } else { | 532 } else { |
533 velocity = new Coordinate(0, 0); | 533 velocity = new Coordinate(0, 0); |
534 } | 534 } |
535 _moves.clear(); | 535 _moves.clear(); |
536 if (_stepTimeout !== null) { | 536 if (_stepTimeout != null) { |
537 Env.cancelRequestAnimationFrame(_stepTimeout); | 537 Env.cancelRequestAnimationFrame(_stepTimeout); |
538 _stepTimeout = null; | 538 _stepTimeout = null; |
539 } | 539 } |
540 if (wasDecelerating) { | 540 if (wasDecelerating) { |
541 _delegate.onDecelerationEnd(); | 541 _delegate.onDecelerationEnd(); |
542 } | 542 } |
543 return velocity; | 543 return velocity; |
544 } | 544 } |
545 | 545 |
546 Coordinate get destination { | 546 Coordinate get destination { |
547 if (!_moves.isEmpty) { | 547 if (!_moves.isEmpty) { |
548 final lastMove = _moves.last; | 548 final lastMove = _moves.last; |
549 return new Coordinate(lastMove.x, lastMove.y); | 549 return new Coordinate(lastMove.x, lastMove.y); |
550 } else { | 550 } else { |
551 return null; | 551 return null; |
552 } | 552 } |
553 } | 553 } |
554 } | 554 } |
OLD | NEW |