Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2481)

Unified Diff: cc/animation/scroll_offset_animation_curve.cc

Issue 1553603003: Tweak the math in ScrollOffsetAnimationCurve::UpdateTarget. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | cc/animation/scroll_offset_animation_curve_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/animation/scroll_offset_animation_curve.cc
diff --git a/cc/animation/scroll_offset_animation_curve.cc b/cc/animation/scroll_offset_animation_curve.cc
index 6cd823f03c7f832cb698cd6bf3e2970f59740d4e..7b8708198969c071d1af3052c3aed6746f31e973 100644
--- a/cc/animation/scroll_offset_animation_curve.cc
+++ b/cc/animation/scroll_offset_animation_curve.cc
@@ -19,6 +19,8 @@ namespace cc {
namespace {
+const double kEpsilon = 0.01f;
+
static float MaximumDimension(const gfx::Vector2dF& delta) {
return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y();
}
@@ -125,6 +127,31 @@ scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const {
return std::move(curve_clone);
}
+static double VelocityBasedDurationBound(gfx::Vector2dF old_delta,
+ double old_velocity,
+ double old_duration,
+ gfx::Vector2dF new_delta) {
+ double old_delta_max_dimension = MaximumDimension(old_delta);
+ double new_delta_max_dimension = MaximumDimension(new_delta);
+
+ // If we are already at the target, stop animating.
+ if (std::abs(new_delta_max_dimension) < kEpsilon)
+ return 0;
+
+ // Guard against division by zero.
+ if (std::abs(old_delta_max_dimension) < kEpsilon ||
+ std::abs(old_velocity) < kEpsilon) {
+ return std::numeric_limits<double>::infinity();
+ }
+
+ // Estimate how long it will take to reach the new target at our present
+ // velocity, with some fudge factor to account for the "ease out".
+ double bound = old_duration / old_velocity * new_delta_max_dimension /
+ old_delta_max_dimension * 2.5f;
ymalik 2015/12/30 19:30:18 I am trying to understand how this gives us the es
skobes 2015/12/30 19:44:20 Sorry it's a little confusing. The old_velocity i
ymalik 2015/12/30 20:09:59 Ah I see. Perhaps putting it in parentheses would
skobes 2015/12/30 20:19:43 Done.
+
+ return bound < kEpsilon ? std::numeric_limits<double>::infinity() : bound;
ajuma 2015/12/30 19:58:23 Should this be returning zero rather than infinity
skobes 2015/12/30 20:07:30 The important thing is really to return infinity w
+}
+
void ScrollOffsetAnimationCurve::UpdateTarget(
double t,
const gfx::ScrollOffset& new_target) {
@@ -135,22 +162,30 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
double old_duration =
(total_animation_duration_ - last_retarget_).InSecondsF();
- double new_duration =
- SegmentDuration(new_delta, duration_behavior_).InSecondsF();
-
double old_velocity = timing_function_->Velocity(
(t - last_retarget_.InSecondsF()) / old_duration);
+ // Use the velocity-based duration bound when it is less than the constant
+ // segment duration. This minimizes the "rubber-band" bouncing effect when
+ // old_velocity is large and new_delta is small.
+ double new_duration =
+ std::min(SegmentDuration(new_delta, duration_behavior_).InSecondsF(),
+ VelocityBasedDurationBound(old_delta, old_velocity, old_duration,
+ new_delta));
+
+ if (new_duration < kEpsilon) {
+ // We are already at or very close to the new target. Stop animating.
+ target_value_ = new_target;
+ total_animation_duration_ = base::TimeDelta::FromSecondsD(t);
ymalik 2015/12/30 19:30:18 I know that the premise of this condition is that
skobes 2015/12/30 19:44:20 We don't want to treat this as a new segment, sinc
ymalik 2015/12/30 20:09:59 Makes sense. Thanks!
+ return;
+ }
+
// TimingFunction::Velocity gives the slope of the curve from 0 to 1.
// To match the "true" velocity in px/sec we must adjust this slope for
// differences in duration and scroll delta between old and new curves.
- const double kEpsilon = 0.01f;
- double new_delta_max_dimension = MaximumDimension(new_delta);
double new_velocity =
- new_delta_max_dimension < kEpsilon // Guard against division by 0.
- ? old_velocity
- : old_velocity * (new_duration / old_duration) *
- (MaximumDimension(old_delta) / new_delta_max_dimension);
+ old_velocity * (new_duration / old_duration) *
+ (MaximumDimension(old_delta) / MaximumDimension(new_delta));
initial_value_ = current_position;
target_value_ = new_target;
« no previous file with comments | « no previous file | cc/animation/scroll_offset_animation_curve_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698