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 3 // found in the LICENSE file. 4 5 #include "cc/animation/scrollbar_animation_controller_thinning.h" 6 7 #include "base/time/time.h" 8 #include "cc/layers/layer_impl.h" 9 #include "cc/layers/scrollbar_layer_impl_base.h" 10 11 namespace { 12 const float kIdleThicknessScale = 0.4f; 13 const float kIdleOpacity = 0.7f; 14 const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; 15 } 16 17 namespace cc { 18 19 scoped_ptr<ScrollbarAnimationControllerThinning> 20 ScrollbarAnimationControllerThinning::Create( 21 LayerImpl* scroll_layer, 22 ScrollbarAnimationControllerClient* client, 23 base::TimeDelta delay_before_starting, 24 base::TimeDelta duration) { 25 return make_scoped_ptr(new ScrollbarAnimationControllerThinning( 26 scroll_layer, client, delay_before_starting, duration)); 27 } 28 29 ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning( 30 LayerImpl* scroll_layer, 31 ScrollbarAnimationControllerClient* client, 32 base::TimeDelta delay_before_starting, 33 base::TimeDelta duration) 34 : ScrollbarAnimationController(client, delay_before_starting, duration), 35 scroll_layer_(scroll_layer), 36 mouse_is_over_scrollbar_(false), 37 mouse_is_near_scrollbar_(false), 38 thickness_change_(NONE), 39 opacity_change_(NONE), 40 mouse_move_distance_to_trigger_animation_( 41 kDefaultMouseMoveDistanceToTriggerAnimation) { 42 ApplyOpacityAndThumbThicknessScale(kIdleOpacity, kIdleThicknessScale); 43 } 44 45 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() { 46 } 47 48 void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) { 49 float opacity = OpacityAtAnimationProgress(progress); 50 float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress( 51 progress); 52 ApplyOpacityAndThumbThicknessScale(opacity, thumb_thickness_scale); 53 if (progress == 1.f) { 54 opacity_change_ = NONE; 55 thickness_change_ = NONE; 56 StopAnimation(); 57 } 58 } 59 60 void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar() { 61 mouse_is_over_scrollbar_ = false; 62 mouse_is_near_scrollbar_ = false; 63 opacity_change_ = DECREASE; 64 thickness_change_ = DECREASE; 65 StartAnimation(); 66 } 67 68 void ScrollbarAnimationControllerThinning::DidScrollUpdate() { 69 ScrollbarAnimationController::DidScrollUpdate(); 70 ApplyOpacityAndThumbThicknessScale( 71 1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale); 72 73 if (!mouse_is_over_scrollbar_) 74 opacity_change_ = DECREASE; 75 } 76 77 void ScrollbarAnimationControllerThinning::DidMouseMoveNear(float distance) { 78 bool mouse_is_over_scrollbar = distance == 0.0; 79 bool mouse_is_near_scrollbar = 80 distance < mouse_move_distance_to_trigger_animation_; 81 82 if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ && 83 mouse_is_near_scrollbar == mouse_is_near_scrollbar_) 84 return; 85 86 if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar) { 87 mouse_is_over_scrollbar_ = mouse_is_over_scrollbar; 88 opacity_change_ = mouse_is_over_scrollbar_ ? INCREASE : DECREASE; 89 } 90 91 if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) { 92 mouse_is_near_scrollbar_ = mouse_is_near_scrollbar; 93 thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE; 94 } 95 96 StartAnimation(); 97 } 98 99 float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress( 100 float progress) { 101 if (opacity_change_ == NONE) 102 return mouse_is_over_scrollbar_ ? 1.f : kIdleOpacity; 103 float factor = opacity_change_ == INCREASE ? progress : (1.f - progress); 104 float ret = ((1.f - kIdleOpacity) * factor) + kIdleOpacity; 105 return ret; 106 } 107 108 float 109 ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress( 110 float progress) { 111 if (thickness_change_ == NONE) 112 return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale; 113 float factor = thickness_change_ == INCREASE ? progress : (1.f - progress); 114 return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale; 115 } 116 117 float ScrollbarAnimationControllerThinning::AdjustScale( 118 float new_value, 119 float current_value, 120 AnimationChange animation_change) { 121 if (animation_change == INCREASE && current_value > new_value) 122 return current_value; 123 if (animation_change == DECREASE && current_value < new_value) 124 return current_value; 125 return new_value; 126 } 127 128 void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale( 129 float opacity, float thumb_thickness_scale) { 130 if (!scroll_layer_->scrollbars()) 131 return; 132 133 LayerImpl::ScrollbarSet* scrollbars = scroll_layer_->scrollbars(); 134 for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin(); 135 it != scrollbars->end(); 136 ++it) { 137 ScrollbarLayerImplBase* scrollbar = *it; 138 if (scrollbar->is_overlay_scrollbar()) { 139 scrollbar->SetOpacity( 140 AdjustScale(opacity, scrollbar->opacity(), opacity_change_)); 141 scrollbar->SetThumbThicknessScaleFactor( 142 AdjustScale(thumb_thickness_scale, 143 scrollbar->thumb_thickness_scale_factor(), 144 thickness_change_)); 145 } 146 } 147 } 148 149 } // namespace cc 150