14
14
#include " cc/base/time_util.h"
15
15
#include " ui/gfx/animation/tween.h"
16
16
17
- using DurationBehavior = cc::ScrollOffsetAnimationCurve::DurationBehavior;
18
-
19
17
const double kConstantDuration = 9.0 ;
20
18
const double kDurationDivisor = 60.0 ;
21
19
@@ -44,7 +42,7 @@ static float MaximumDimension(const gfx::Vector2dF& delta) {
44
42
return std::abs (delta.x ()) > std::abs (delta.y ()) ? delta.x () : delta.y ();
45
43
}
46
44
47
- static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity (
45
+ static std::unique_ptr<TimingFunction> EaseInOutWithInitialVelocity (
48
46
double velocity) {
49
47
// Clamp velocity to a sane value.
50
48
velocity = base::ClampToRange (velocity, -1000.0 , 1000.0 );
@@ -61,33 +59,30 @@ static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity(
61
59
base::Optional<double >
62
60
ScrollOffsetAnimationCurve::animation_duration_for_testing_;
63
61
64
- std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurve::Create (
65
- const gfx::ScrollOffset& target_value,
66
- std::unique_ptr<TimingFunction> timing_function,
67
- DurationBehavior duration_behavior) {
68
- return base::WrapUnique (new ScrollOffsetAnimationCurve (
69
- target_value, std::move (timing_function), duration_behavior));
70
- }
71
-
72
62
ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve (
73
63
const gfx::ScrollOffset& target_value,
74
64
std::unique_ptr<TimingFunction> timing_function,
75
- DurationBehavior duration_behavior)
65
+ AnimationType animation_type,
66
+ base::Optional<DurationBehavior> duration_behavior)
76
67
: target_value_(target_value),
77
68
timing_function_ (std::move(timing_function)),
69
+ animation_type_(animation_type),
78
70
duration_behavior_(duration_behavior),
79
- has_set_initial_value_(false ) {}
71
+ has_set_initial_value_(false ) {
72
+ DCHECK_EQ ((animation_type == AnimationType::kEaseInOut ),
73
+ duration_behavior.has_value ());
74
+ }
80
75
81
76
ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve () = default ;
82
77
83
- base::TimeDelta ScrollOffsetAnimationCurve::SegmentDuration (
78
+ // static
79
+ base::TimeDelta ScrollOffsetAnimationCurve::EaseInOutSegmentDuration (
84
80
const gfx::Vector2dF& delta,
85
- DurationBehavior behavior,
86
- base::TimeDelta delayed_by,
87
- float velocity) {
81
+ DurationBehavior duration_behavior,
82
+ base::TimeDelta delayed_by) {
88
83
double duration = kConstantDuration ;
89
84
if (!animation_duration_for_testing_) {
90
- switch (behavior ) {
85
+ switch (duration_behavior ) {
91
86
case DurationBehavior::CONSTANT:
92
87
duration = kConstantDuration ;
93
88
break ;
@@ -102,24 +97,33 @@ base::TimeDelta ScrollOffsetAnimationCurve::SegmentDuration(
102
97
duration = base::ClampToRange (duration, kInverseDeltaMinDuration ,
103
98
kInverseDeltaMaxDuration );
104
99
break ;
105
- case DurationBehavior::CONSTANT_VELOCITY:
106
- duration =
107
- std::abs (MaximumDimension (delta) / velocity * kDurationDivisor );
108
- break ;
109
- default :
110
- NOTREACHED ();
111
100
}
101
+ duration /= kDurationDivisor ;
112
102
} else {
113
103
duration = animation_duration_for_testing_.value ();
114
104
}
115
105
116
- base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds (
117
- duration / kDurationDivisor * base::Time::kMicrosecondsPerSecond );
106
+ base::TimeDelta delay_adjusted_duration =
107
+ base::TimeDelta::FromSecondsD (duration) - delayed_by;
108
+ return (delay_adjusted_duration >= base::TimeDelta ())
109
+ ? delay_adjusted_duration
110
+ : base::TimeDelta ();
111
+ }
118
112
119
- time_delta -= delayed_by;
120
- if (time_delta >= base::TimeDelta ())
121
- return time_delta;
122
- return base::TimeDelta ();
113
+ // static
114
+ base::TimeDelta ScrollOffsetAnimationCurve::LinearSegmentDuration (
115
+ const gfx::Vector2dF& delta,
116
+ base::TimeDelta delayed_by,
117
+ float velocity) {
118
+ double duration_in_seconds =
119
+ (animation_duration_for_testing_.has_value ())
120
+ ? animation_duration_for_testing_.value ()
121
+ : std::abs (MaximumDimension (delta) / velocity);
122
+ base::TimeDelta delay_adjusted_duration =
123
+ base::TimeDelta::FromSecondsD (duration_in_seconds) - delayed_by;
124
+ return (delay_adjusted_duration >= base::TimeDelta ())
125
+ ? delay_adjusted_duration
126
+ : base::TimeDelta ();
123
127
}
124
128
125
129
void ScrollOffsetAnimationCurve::SetInitialValue (
@@ -128,9 +132,17 @@ void ScrollOffsetAnimationCurve::SetInitialValue(
128
132
float velocity) {
129
133
initial_value_ = initial_value;
130
134
has_set_initial_value_ = true ;
131
- total_animation_duration_ =
132
- SegmentDuration (target_value_.DeltaFrom (initial_value_),
133
- duration_behavior_, delayed_by, velocity);
135
+ gfx::Vector2dF delta = target_value_.DeltaFrom (initial_value);
136
+ switch (animation_type_) {
137
+ case AnimationType::kEaseInOut :
138
+ total_animation_duration_ = EaseInOutSegmentDuration (
139
+ delta, duration_behavior_.value (), delayed_by);
140
+ break ;
141
+ case AnimationType::kLinear :
142
+ total_animation_duration_ =
143
+ LinearSegmentDuration (delta, delayed_by, velocity);
144
+ break ;
145
+ }
134
146
}
135
147
136
148
bool ScrollOffsetAnimationCurve::HasSetInitialValue () const {
@@ -159,10 +171,10 @@ gfx::ScrollOffset ScrollOffsetAnimationCurve::GetValue(
159
171
160
172
double progress = timing_function_->GetValue (TimeUtil::Divide (t, duration));
161
173
return gfx::ScrollOffset (
162
- gfx::Tween::FloatValueBetween (
163
- progress, initial_value_. x (), target_value_.x ()),
164
- gfx::Tween::FloatValueBetween (
165
- progress, initial_value_. y (), target_value_.y ()));
174
+ gfx::Tween::FloatValueBetween (progress, initial_value_. x (),
175
+ target_value_.x ()),
176
+ gfx::Tween::FloatValueBetween (progress, initial_value_. y (),
177
+ target_value_.y ()));
166
178
}
167
179
168
180
base::TimeDelta ScrollOffsetAnimationCurve::Duration () const {
@@ -181,8 +193,9 @@ std::unique_ptr<ScrollOffsetAnimationCurve>
181
193
ScrollOffsetAnimationCurve::CloneToScrollOffsetAnimationCurve () const {
182
194
std::unique_ptr<TimingFunction> timing_function (
183
195
static_cast <TimingFunction*>(timing_function_->Clone ().release ()));
184
- std::unique_ptr<ScrollOffsetAnimationCurve> curve_clone =
185
- Create (target_value_, std::move (timing_function), duration_behavior_);
196
+ std::unique_ptr<ScrollOffsetAnimationCurve> curve_clone = base::WrapUnique (
197
+ new ScrollOffsetAnimationCurve (target_value_, std::move (timing_function),
198
+ animation_type_, duration_behavior_));
186
199
curve_clone->initial_value_ = initial_value_;
187
200
curve_clone->total_animation_duration_ = total_animation_duration_;
188
201
curve_clone->last_retarget_ = last_retarget_;
@@ -192,7 +205,7 @@ ScrollOffsetAnimationCurve::CloneToScrollOffsetAnimationCurve() const {
192
205
193
206
void ScrollOffsetAnimationCurve::SetAnimationDurationForTesting (
194
207
base::TimeDelta duration) {
195
- animation_duration_for_testing_ = duration.InSecondsF () * kDurationDivisor ;
208
+ animation_duration_for_testing_ = duration.InSecondsF ();
196
209
}
197
210
198
211
static base::TimeDelta VelocityBasedDurationBound (
@@ -227,6 +240,15 @@ static base::TimeDelta VelocityBasedDurationBound(
227
240
void ScrollOffsetAnimationCurve::UpdateTarget (
228
241
base::TimeDelta t,
229
242
const gfx::ScrollOffset& new_target) {
243
+ DCHECK_NE (animation_type_, AnimationType::kLinear )
244
+ << " UpdateTarget is not supported on linear scroll animations." ;
245
+ EaseInOutUpdateTarget (t, new_target);
246
+ }
247
+
248
+ void ScrollOffsetAnimationCurve::EaseInOutUpdateTarget (
249
+ base::TimeDelta t,
250
+ const gfx::ScrollOffset& new_target) {
251
+ DCHECK_EQ (animation_type_, AnimationType::kEaseInOut );
230
252
if (std::abs (MaximumDimension (target_value_.DeltaFrom (new_target))) <
231
253
kEpsilon ) {
232
254
target_value_ = new_target;
@@ -243,8 +265,8 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
243
265
// The last segment was of zero duration.
244
266
if ((total_animation_duration_ - last_retarget_).is_zero ()) {
245
267
DCHECK_EQ (t, last_retarget_);
246
- total_animation_duration_ = SegmentDuration (new_delta, duration_behavior_,
247
- delayed_by, /* velocity */ 0 );
268
+ total_animation_duration_ = EaseInOutSegmentDuration (
269
+ new_delta, duration_behavior_. value (), delayed_by );
248
270
target_value_ = new_target;
249
271
return ;
250
272
}
@@ -257,8 +279,8 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
257
279
// segment duration. This minimizes the "rubber-band" bouncing effect when
258
280
// old_normalized_velocity is large and new_delta is small.
259
281
base::TimeDelta new_duration =
260
- std::min (SegmentDuration (new_delta, duration_behavior_, delayed_by ,
261
- /* velocity */ 0 ),
282
+ std::min (EaseInOutSegmentDuration (new_delta, duration_behavior_. value () ,
283
+ delayed_by ),
262
284
VelocityBasedDurationBound (old_delta, old_normalized_velocity,
263
285
old_duration, new_delta));
264
286
@@ -281,7 +303,7 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
281
303
target_value_ = new_target;
282
304
total_animation_duration_ = t + new_duration;
283
305
last_retarget_ = t;
284
- timing_function_ = EaseOutWithInitialVelocity (new_normalized_velocity);
306
+ timing_function_ = EaseInOutWithInitialVelocity (new_normalized_velocity);
285
307
}
286
308
287
309
} // namespace cc
0 commit comments