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 private static final float FINISHING_ACCELERATION = 7.0f; |
| 14 private static final float ACCELERATION = 0.15f; |
| 15 private static final float DECELERATION = 0.15f; |
| 16 |
| 17 // Precomputed constants |
| 18 private static final float CONSTANT_1 = -1.0f / ACCELERATION; |
| 19 private static final float CONSTANT_2 = 2.0f * DECELERATION |
| 20 / ((DECELERATION + ACCELERATION) * ACCELERATION); |
| 21 private static final float CONSTANT_3 = DECELERATION |
| 22 / ((DECELERATION + ACCELERATION) * ACCELERATION * ACCELERATION); |
| 23 |
| 24 private float mProgress; |
| 25 private float mVelocity; |
| 26 |
| 27 @Override |
| 28 public void reset() { |
| 29 mProgress = 0.0f; |
| 30 mVelocity = 0.0f; |
| 31 } |
| 32 |
| 33 @Override |
| 34 public float updateProgress(float targetProgress, float frameTimeSec, int re
solution) { |
| 35 assert mProgress <= targetProgress; |
| 36 |
| 37 final float acceleratingDuration = computeAcceleratingDuration( |
| 38 targetProgress, frameTimeSec); |
| 39 final float deceleratingDuration = frameTimeSec - acceleratingDuration; |
| 40 |
| 41 if (acceleratingDuration > 0.0f) { |
| 42 float velocityChange = (targetProgress == 1.0f ? FINISHING_ACCELERAT
ION : ACCELERATION) |
| 43 * acceleratingDuration; |
| 44 mProgress += (mVelocity + 0.5f * velocityChange) * acceleratingDurat
ion; |
| 45 mVelocity += velocityChange; |
| 46 } |
| 47 |
| 48 if (deceleratingDuration > 0.0f) { |
| 49 float velocityChange = -DECELERATION * deceleratingDuration; |
| 50 mProgress += (mVelocity + 0.5f * velocityChange) * deceleratingDurat
ion; |
| 51 mVelocity += velocityChange; |
| 52 } |
| 53 |
| 54 mProgress = Math.min(mProgress, targetProgress); |
| 55 if (targetProgress - mProgress < 0.5f / resolution) { |
| 56 mProgress = targetProgress; |
| 57 mVelocity = 0.0f; |
| 58 } |
| 59 |
| 60 return mProgress; |
| 61 } |
| 62 |
| 63 /** |
| 64 * Computes and returns accelerating duration. |
| 65 * |
| 66 * Symbol Description Corresponding variable |
| 67 * v_0 Initial velocity mVelocity |
| 68 * A Acceleration ACCELERATION |
| 69 * D Deceleration DECELERATION |
| 70 * d_A Accelerating duration |
| 71 * d_D Decelerating duration |
| 72 * |
| 73 * Given the initial position and the initial velocity, we assume that it ac
celerates constantly |
| 74 * and then decelerates constantly. |
| 75 * |
| 76 * We want to stop smoothly when it reaches the end. Thus zero velocity at t
he end: |
| 77 * v_0 + A d_A - D d_D = 0 |
| 78 * Equation image: http://www.HostMath.com/Show.aspx?Code=v_0%20%2B%20A%20d_
A%20-%20D%20d_D%20%3D%200 |
| 79 * |
| 80 * The traveled distance should be (targetProgress - mProgress): |
| 81 * targetProgress - mProgress = |
| 82 * \int_0^{d_A} (v_0 + A t) dt + \int_0^{d_D} (v_{0} + A d_A - D t)
dt |
| 83 * 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 |
| 84 * |
| 85 * This function solves d_A from the above equations. |
| 86 */ |
| 87 private float computeAcceleratingDuration(float targetProgress, float frameT
imeSec) { |
| 88 if (targetProgress == 1.0f) { |
| 89 return frameTimeSec; |
| 90 } else { |
| 91 float maxAcceleratingDuration = CONSTANT_1 * mVelocity + (float) Mat
h.sqrt( |
| 92 CONSTANT_2 * (targetProgress - mProgress) + CONSTANT_3 * mVe
locity * mVelocity); |
| 93 maxAcceleratingDuration = Math.max(maxAcceleratingDuration, 0.0f); |
| 94 if (frameTimeSec <= maxAcceleratingDuration) { |
| 95 return frameTimeSec; |
| 96 } else { |
| 97 return maxAcceleratingDuration; |
| 98 } |
| 99 } |
| 100 } |
| 101 } |
OLD | NEW |