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

Side by Side Diff: cc/animation/scroll_offset_animation_curve.cc

Issue 393713002: Scroll offset animation curve retargeting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
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 "ui/gfx/animation/tween.h" 12 #include "ui/gfx/animation/tween.h"
13 13
14 const double kDurationDivisor = 60.0; 14 const double kDurationDivisor = 60.0;
15 15
16 namespace cc { 16 namespace cc {
17 17
18 namespace {
19
20 static float maxDelta(gfx::Vector2dF delta) {
ajuma 2014/07/16 20:35:23 MaximumDimension? Or InfinityNorm maybe?
skobes 2014/07/16 21:10:48 Done.
21 return std::max(std::abs(delta.x()), std::abs(delta.y()));
22 }
23
24 static base::TimeDelta durationFromDelta(gfx::Vector2dF delta) {
ajuma 2014/07/16 20:35:23 Nit: function names should start with a capital le
skobes 2014/07/16 21:10:48 Done.
25 // The duration of a scroll animation depends on the size of the scroll.
26 // The exact relationship between the size and the duration isn't specified
27 // by the CSSOM View smooth scroll spec and is instead left up to user agents
28 // to decide. The calculation performed here will very likely be further
29 // tweaked before the smooth scroll API ships.
30 return base::TimeDelta::FromMicroseconds(
31 (std::sqrt(maxDelta(delta)) / kDurationDivisor) *
32 base::Time::kMicrosecondsPerSecond);
33 }
34
35 static scoped_ptr<TimingFunction> easeOutWithInitialVelocity(double velocity) {
ajuma 2014/07/16 20:35:23 EaseOutWithInitialVelocity
skobes 2014/07/16 21:10:48 Done.
36 // Based on EaseInOutTimingFunction::Create with first control point rotated.
37 const double r2 = 0.42 * 0.42;
38 const double v2 = velocity * velocity;
39 const double x1 = std::sqrt(r2 / (v2 + 1));
40 const double y1 = std::sqrt(r2 * v2 / (v2 + 1));
41 return CubicBezierTimingFunction::Create(x1, y1, 0.58, 1)
42 .PassAs<TimingFunction>();
43 }
44
45 } // namespace
46
18 scoped_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurve::Create( 47 scoped_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurve::Create(
19 const gfx::Vector2dF& target_value, 48 const gfx::Vector2dF& target_value,
20 scoped_ptr<TimingFunction> timing_function) { 49 scoped_ptr<TimingFunction> timing_function) {
21 return make_scoped_ptr( 50 return make_scoped_ptr(
22 new ScrollOffsetAnimationCurve(target_value, timing_function.Pass())); 51 new ScrollOffsetAnimationCurve(target_value, timing_function.Pass()));
23 } 52 }
24 53
25 ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve( 54 ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve(
26 const gfx::Vector2dF& target_value, 55 const gfx::Vector2dF& target_value,
27 scoped_ptr<TimingFunction> timing_function) 56 scoped_ptr<TimingFunction> timing_function)
28 : target_value_(target_value), timing_function_(timing_function.Pass()) { 57 : target_value_(target_value), timing_function_(timing_function.Pass()) {
29 } 58 }
30 59
31 ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {} 60 ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {}
32 61
33 void ScrollOffsetAnimationCurve::SetInitialValue( 62 void ScrollOffsetAnimationCurve::SetInitialValue(
34 const gfx::Vector2dF& initial_value) { 63 const gfx::Vector2dF& initial_value) {
35 initial_value_ = initial_value; 64 initial_value_ = initial_value;
36 65 total_animation_duration_ = durationFromDelta(target_value_ - initial_value_);
37 // The duration of a scroll animation depends on the size of the scroll.
38 // The exact relationship between the size and the duration isn't specified
39 // by the CSSOM View smooth scroll spec and is instead left up to user agents
40 // to decide. The calculation performed here will very likely be further
41 // tweaked before the smooth scroll API ships.
42 float delta_x = std::abs(target_value_.x() - initial_value_.x());
43 float delta_y = std::abs(target_value_.y() - initial_value_.y());
44 float max_delta = std::max(delta_x, delta_y);
45 duration_ = base::TimeDelta::FromMicroseconds(
46 (std::sqrt(max_delta) / kDurationDivisor) *
47 base::Time::kMicrosecondsPerSecond);
48 } 66 }
49 67
50 gfx::Vector2dF ScrollOffsetAnimationCurve::GetValue(double t) const { 68 gfx::Vector2dF ScrollOffsetAnimationCurve::GetValue(double t) const {
51 double duration = duration_.InSecondsF(); 69 double duration = (total_animation_duration_ - last_retarget_).InSecondsF();
70 t -= last_retarget_.InSecondsF();
52 71
53 if (t <= 0) 72 if (t <= 0)
54 return initial_value_; 73 return initial_value_;
55 74
56 if (t >= duration) 75 if (t >= duration)
57 return target_value_; 76 return target_value_;
58 77
59 double progress = (timing_function_->GetValue(t / duration)); 78 double progress = (timing_function_->GetValue(t / duration));
60 return gfx::Vector2dF(gfx::Tween::FloatValueBetween( 79 return gfx::Vector2dF(gfx::Tween::FloatValueBetween(
61 progress, initial_value_.x(), target_value_.x()), 80 progress, initial_value_.x(), target_value_.x()),
62 gfx::Tween::FloatValueBetween( 81 gfx::Tween::FloatValueBetween(
63 progress, initial_value_.y(), target_value_.y())); 82 progress, initial_value_.y(), target_value_.y()));
64 } 83 }
65 84
66 double ScrollOffsetAnimationCurve::Duration() const { 85 double ScrollOffsetAnimationCurve::Duration() const {
67 return duration_.InSecondsF(); 86 return total_animation_duration_.InSecondsF();
68 } 87 }
69 88
70 AnimationCurve::CurveType ScrollOffsetAnimationCurve::Type() const { 89 AnimationCurve::CurveType ScrollOffsetAnimationCurve::Type() const {
71 return ScrollOffset; 90 return ScrollOffset;
72 } 91 }
73 92
74 scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const { 93 scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const {
75 scoped_ptr<TimingFunction> timing_function( 94 scoped_ptr<TimingFunction> timing_function(
76 static_cast<TimingFunction*>(timing_function_->Clone().release())); 95 static_cast<TimingFunction*>(timing_function_->Clone().release()));
77 scoped_ptr<ScrollOffsetAnimationCurve> curve_clone = 96 scoped_ptr<ScrollOffsetAnimationCurve> curve_clone =
78 Create(target_value_, timing_function.Pass()); 97 Create(target_value_, timing_function.Pass());
79 curve_clone->initial_value_ = initial_value_; 98 curve_clone->initial_value_ = initial_value_;
80 curve_clone->duration_ = duration_; 99 curve_clone->total_animation_duration_ = total_animation_duration_;
100 curve_clone->last_retarget_ = last_retarget_;
81 return curve_clone.PassAs<AnimationCurve>(); 101 return curve_clone.PassAs<AnimationCurve>();
82 } 102 }
83 103
104 void ScrollOffsetAnimationCurve::UpdateTarget(
105 double t,
106 const gfx::Vector2dF& new_target) {
107 gfx::Vector2dF current_position = GetValue(t);
108 gfx::Vector2dF old_delta = target_value_ - initial_value_;
109 gfx::Vector2dF new_delta = new_target - current_position;
110
111 double old_duration =
112 (total_animation_duration_ - last_retarget_).InSecondsF();
113 double new_duration = durationFromDelta(new_delta).InSecondsF();
114
115 double old_velocity = timing_function_->Velocity(
116 (t - last_retarget_.InSecondsF()) / old_duration);
117 double new_velocity = old_velocity * (new_duration / old_duration) *
118 (maxDelta(old_delta) / maxDelta(new_delta));
ajuma 2014/07/16 20:35:23 Please add a comment explaining why the new veloci
skobes 2014/07/16 21:10:48 Done.
119
120 initial_value_ = current_position;
121 target_value_ = new_target;
122 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration);
123 last_retarget_ = base::TimeDelta::FromSecondsD(t);
124 timing_function_ = easeOutWithInitialVelocity(new_velocity);
125 }
126
84 } // namespace cc 127 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698