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

Side by Side 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 4 years, 11 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | cc/animation/scroll_offset_animation_curve_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/animation/scroll_offset_animation_curve.h" 5 #include "cc/animation/scroll_offset_animation_curve.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "cc/animation/timing_function.h" 11 #include "cc/animation/timing_function.h"
12 #include "cc/base/time_util.h" 12 #include "cc/base/time_util.h"
13 #include "ui/gfx/animation/tween.h" 13 #include "ui/gfx/animation/tween.h"
14 14
15 const double kConstantDuration = 12.0; 15 const double kConstantDuration = 12.0;
16 const double kDurationDivisor = 60.0; 16 const double kDurationDivisor = 60.0;
17 17
18 namespace cc { 18 namespace cc {
19 19
20 namespace { 20 namespace {
21 21
22 const double kEpsilon = 0.01f;
23
22 static float MaximumDimension(const gfx::Vector2dF& delta) { 24 static float MaximumDimension(const gfx::Vector2dF& delta) {
23 return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y(); 25 return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y();
24 } 26 }
25 27
26 static base::TimeDelta SegmentDuration( 28 static base::TimeDelta SegmentDuration(
27 const gfx::Vector2dF& delta, 29 const gfx::Vector2dF& delta,
28 ScrollOffsetAnimationCurve::DurationBehavior behavior) { 30 ScrollOffsetAnimationCurve::DurationBehavior behavior) {
29 if (behavior == ScrollOffsetAnimationCurve::DurationBehavior::DELTA_BASED) { 31 if (behavior == ScrollOffsetAnimationCurve::DurationBehavior::DELTA_BASED) {
30 // The duration of a JS scroll animation depends on the size of the scroll. 32 // The duration of a JS scroll animation depends on the size of the scroll.
31 // The exact relationship between the size and the duration isn't specified 33 // The exact relationship between the size and the duration isn't specified
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 static_cast<TimingFunction*>(timing_function_->Clone().release())); 120 static_cast<TimingFunction*>(timing_function_->Clone().release()));
119 scoped_ptr<ScrollOffsetAnimationCurve> curve_clone = 121 scoped_ptr<ScrollOffsetAnimationCurve> curve_clone =
120 Create(target_value_, std::move(timing_function), duration_behavior_); 122 Create(target_value_, std::move(timing_function), duration_behavior_);
121 curve_clone->initial_value_ = initial_value_; 123 curve_clone->initial_value_ = initial_value_;
122 curve_clone->total_animation_duration_ = total_animation_duration_; 124 curve_clone->total_animation_duration_ = total_animation_duration_;
123 curve_clone->last_retarget_ = last_retarget_; 125 curve_clone->last_retarget_ = last_retarget_;
124 curve_clone->has_set_initial_value_ = has_set_initial_value_; 126 curve_clone->has_set_initial_value_ = has_set_initial_value_;
125 return std::move(curve_clone); 127 return std::move(curve_clone);
126 } 128 }
127 129
130 static double VelocityBasedDurationBound(gfx::Vector2dF old_delta,
131 double old_velocity,
132 double old_duration,
133 gfx::Vector2dF new_delta) {
134 double old_delta_max_dimension = MaximumDimension(old_delta);
135 double new_delta_max_dimension = MaximumDimension(new_delta);
136
137 // If we are already at the target, stop animating.
138 if (std::abs(new_delta_max_dimension) < kEpsilon)
139 return 0;
140
141 // Guard against division by zero.
142 if (std::abs(old_delta_max_dimension) < kEpsilon ||
143 std::abs(old_velocity) < kEpsilon) {
144 return std::numeric_limits<double>::infinity();
145 }
146
147 // Estimate how long it will take to reach the new target at our present
148 // velocity, with some fudge factor to account for the "ease out".
149 double bound = old_duration / old_velocity * new_delta_max_dimension /
150 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.
151
152 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
153 }
154
128 void ScrollOffsetAnimationCurve::UpdateTarget( 155 void ScrollOffsetAnimationCurve::UpdateTarget(
129 double t, 156 double t,
130 const gfx::ScrollOffset& new_target) { 157 const gfx::ScrollOffset& new_target) {
131 gfx::ScrollOffset current_position = 158 gfx::ScrollOffset current_position =
132 GetValue(base::TimeDelta::FromSecondsD(t)); 159 GetValue(base::TimeDelta::FromSecondsD(t));
133 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_); 160 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
134 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position); 161 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position);
135 162
136 double old_duration = 163 double old_duration =
137 (total_animation_duration_ - last_retarget_).InSecondsF(); 164 (total_animation_duration_ - last_retarget_).InSecondsF();
138 double new_duration =
139 SegmentDuration(new_delta, duration_behavior_).InSecondsF();
140
141 double old_velocity = timing_function_->Velocity( 165 double old_velocity = timing_function_->Velocity(
142 (t - last_retarget_.InSecondsF()) / old_duration); 166 (t - last_retarget_.InSecondsF()) / old_duration);
143 167
168 // Use the velocity-based duration bound when it is less than the constant
169 // segment duration. This minimizes the "rubber-band" bouncing effect when
170 // old_velocity is large and new_delta is small.
171 double new_duration =
172 std::min(SegmentDuration(new_delta, duration_behavior_).InSecondsF(),
173 VelocityBasedDurationBound(old_delta, old_velocity, old_duration,
174 new_delta));
175
176 if (new_duration < kEpsilon) {
177 // We are already at or very close to the new target. Stop animating.
178 target_value_ = new_target;
179 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!
180 return;
181 }
182
144 // TimingFunction::Velocity gives the slope of the curve from 0 to 1. 183 // TimingFunction::Velocity gives the slope of the curve from 0 to 1.
145 // To match the "true" velocity in px/sec we must adjust this slope for 184 // To match the "true" velocity in px/sec we must adjust this slope for
146 // differences in duration and scroll delta between old and new curves. 185 // differences in duration and scroll delta between old and new curves.
147 const double kEpsilon = 0.01f;
148 double new_delta_max_dimension = MaximumDimension(new_delta);
149 double new_velocity = 186 double new_velocity =
150 new_delta_max_dimension < kEpsilon // Guard against division by 0. 187 old_velocity * (new_duration / old_duration) *
151 ? old_velocity 188 (MaximumDimension(old_delta) / MaximumDimension(new_delta));
152 : old_velocity * (new_duration / old_duration) *
153 (MaximumDimension(old_delta) / new_delta_max_dimension);
154 189
155 initial_value_ = current_position; 190 initial_value_ = current_position;
156 target_value_ = new_target; 191 target_value_ = new_target;
157 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration); 192 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration);
158 last_retarget_ = base::TimeDelta::FromSecondsD(t); 193 last_retarget_ = base::TimeDelta::FromSecondsD(t);
159 timing_function_ = EaseOutWithInitialVelocity(new_velocity); 194 timing_function_ = EaseOutWithInitialVelocity(new_velocity);
160 } 195 }
161 196
162 } // namespace cc 197 } // namespace cc
OLDNEW
« 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