OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.widget; |
| 6 |
| 7 /** |
| 8 * Progress bar animation logic that smoothly accelerates in the beginning and s
moothly decelerates |
| 9 * towards the end. The model is applying a constant acceleration followed by a
constant |
| 10 * deceleration. |
| 11 */ |
| 12 class ProgressAnimationSmooth implements ToolbarProgressBar.AnimationLogic { |
| 13 // The (de)acceleration unit is progress per second squared where 0 <= progr
ess <= 1. |
| 14 private static final float FINISHING_ACCELERATION = 7.0f; |
| 15 private static final float ACCELERATION = 0.15f; |
| 16 private static final float DECELERATION = 0.15f; |
| 17 |
| 18 // Precomputed constants |
| 19 private static final float CONSTANT_1 = -1.0f / ACCELERATION; |
| 20 private static final float CONSTANT_2 = 2.0f * DECELERATION |
| 21 / ((DECELERATION + ACCELERATION) * ACCELERATION); |
| 22 private static final float CONSTANT_3 = DECELERATION |
| 23 / ((DECELERATION + ACCELERATION) * ACCELERATION * ACCELERATION); |
| 24 |
| 25 private float mProgress; |
| 26 private float mVelocity; |
| 27 |
| 28 @Override |
| 29 public void reset() { |
| 30 mProgress = 0.0f; |
| 31 mVelocity = 0.0f; |
| 32 } |
| 33 |
| 34 @Override |
| 35 public float updateProgress(float targetProgress, float frameTimeSec, int re
solution) { |
| 36 assert mProgress <= targetProgress; |
| 37 |
| 38 final float acceleratingDuration = computeAcceleratingDuration( |
| 39 targetProgress, frameTimeSec); |
| 40 final float deceleratingDuration = frameTimeSec - acceleratingDuration; |
| 41 |
| 42 if (acceleratingDuration > 0.0f) { |
| 43 float velocityChange = (targetProgress == 1.0f ? FINISHING_ACCELERAT
ION : ACCELERATION) |
| 44 * acceleratingDuration; |
| 45 mProgress += (mVelocity + 0.5f * velocityChange) * acceleratingDurat
ion; |
| 46 mVelocity += velocityChange; |
| 47 } |
| 48 |
| 49 if (deceleratingDuration > 0.0f) { |
| 50 float velocityChange = -DECELERATION * deceleratingDuration; |
| 51 mProgress += (mVelocity + 0.5f * velocityChange) * deceleratingDurat
ion; |
| 52 mVelocity += velocityChange; |
| 53 } |
| 54 |
| 55 mProgress = Math.min(mProgress, targetProgress); |
| 56 if (targetProgress - mProgress < 0.5f / resolution) { |
| 57 mProgress = targetProgress; |
| 58 mVelocity = 0.0f; |
| 59 } |
| 60 |
| 61 return mProgress; |
| 62 } |
| 63 |
| 64 /** |
| 65 * Computes and returns accelerating duration. |
| 66 * |
| 67 * Symbol Description Corresponding variable |
| 68 * v_0 Initial velocity mVelocity |
| 69 * A Acceleration ACCELERATION |
| 70 * D Deceleration DECELERATION |
| 71 * d_A Accelerating duration |
| 72 * d_D Decelerating duration |
| 73 * |
| 74 * Given the initial position and the initial velocity, we assume that it ac
celerates constantly |
| 75 * and then decelerates constantly. |
| 76 * |
| 77 * We want to stop smoothly when it reaches the end. Thus zero velocity at t
he end: |
| 78 * v_0 + A d_A - D d_D = 0 |
| 79 * Equation image: http://www.HostMath.com/Show.aspx?Code=v_0%20%2B%20A%20d_
A%20-%20D%20d_D%20%3D%200 |
| 80 * |
| 81 * The traveled distance should be (targetProgress - mProgress): |
| 82 * targetProgress - mProgress = |
| 83 * \int_0^{d_A} (v_0 + A t) dt + \int_0^{d_D} (v_{0} + A d_A - D t)
dt |
| 84 * Equation image: http://www.HostMath.com/Show.aspx?Code=targetProgress%20-
%20mProgress%20%3D%20%5Cint_0%5E%7Bd_A%7D%20(v_0%20%2B%20A%20t)%20dt%20%2B%20%5C
int_0%5E%7Bd_D%7D%20(v_%7B0%7D%20%2B%20A%20d_A%20-%20D%20t)dt |
| 85 * |
| 86 * This function solves d_A from the above equations. |
| 87 */ |
| 88 private float computeAcceleratingDuration(float targetProgress, float frameT
imeSec) { |
| 89 if (targetProgress == 1.0f) { |
| 90 return frameTimeSec; |
| 91 } else { |
| 92 float maxAcceleratingDuration = CONSTANT_1 * mVelocity + (float) Mat
h.sqrt( |
| 93 CONSTANT_2 * (targetProgress - mProgress) + CONSTANT_3 * mVe
locity * mVelocity); |
| 94 maxAcceleratingDuration = Math.max(maxAcceleratingDuration, 0.0f); |
| 95 if (frameTimeSec <= maxAcceleratingDuration) { |
| 96 return frameTimeSec; |
| 97 } else { |
| 98 return maxAcceleratingDuration; |
| 99 } |
| 100 } |
| 101 } |
| 102 } |
OLD | NEW |