1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components/scroll/scroll_fade_effect.h"
17
18 namespace OHOS::Ace {
19
InitialEdgeEffect()20 void ScrollFadeEffect::InitialEdgeEffect()
21 {
22 ResetFadeEffect(fadeColor_);
23 }
24
ResetFadeEffect(const Color & color)25 void ScrollFadeEffect::ResetFadeEffect(const Color& color)
26 {
27 fadeColor_ = color;
28 if (!fadePainter_) {
29 fadePainter_ = ScrollFadePainter::CreatePainter();
30 }
31
32 if (!fadeController_) {
33 auto scroll = scroll_.Upgrade();
34 fadeController_ = AceType::MakeRefPtr<ScrollFadeController>(scroll ? scroll->GetContext() : nullptr);
35 fadeController_->SetCallback([weakFade = AceType::WeakClaim(this)](double opacity, double scale) {
36 auto fade = weakFade.Upgrade();
37 if (fade) {
38 fade->SetOpacityAndScale(opacity, scale);
39 }
40 });
41 }
42 }
43
CalculateOverScroll(double oldPosition,bool isReachMax)44 double ScrollFadeEffect::CalculateOverScroll(double oldPosition, bool isReachMax)
45 {
46 if (!currentPositionCallback_ || !leadingCallback_ || !trailingCallback_) {
47 LOGD("position callback is null");
48 return 0.0;
49 }
50
51 double newPosition = -currentPositionCallback_();
52 double minExtent = -trailingCallback_();
53 double maxExtent = -leadingCallback_();
54
55 // under scroll
56 if (newPosition < oldPosition && oldPosition <= minExtent) {
57 return newPosition - oldPosition;
58 }
59
60 // over scroll
61 if (newPosition > oldPosition && oldPosition >= maxExtent) {
62 return newPosition - oldPosition;
63 }
64
65 // crash the top
66 if (newPosition < minExtent && oldPosition > minExtent) {
67 LOGD("crash the top");
68 return newPosition;
69 }
70
71 // crash the bottom
72 if (newPosition > maxExtent && maxExtent > oldPosition && isReachMax) {
73 LOGD("crash the bottom");
74 return newPosition - maxExtent;
75 }
76
77 return 0.0;
78 }
79
SetPaintDirection(Axis axis,double overScroll)80 void ScrollFadeEffect::SetPaintDirection(Axis axis, double overScroll)
81 {
82 if (NearZero(overScroll) || !fadePainter_) {
83 return;
84 }
85 auto const isVertical = axis == Axis::VERTICAL;
86 if (isVertical && overScroll < 0.0) {
87 fadePainter_->SetDirection(OverScrollDirection::UP);
88 } else if (isVertical && overScroll > 0.0) {
89 fadePainter_->SetDirection(OverScrollDirection::DOWN);
90 } else if (overScroll < 0.0) {
91 fadePainter_->SetDirection(OverScrollDirection::LEFT);
92 } else {
93 fadePainter_->SetDirection(OverScrollDirection::RIGHT);
94 }
95 }
96
Paint(RenderContext & context,const Size & viewPort,const Offset & offset)97 void ScrollFadeEffect::Paint(
98 RenderContext& context, const Size& viewPort, const Offset& offset)
99 {
100 if (fadePainter_) {
101 fadePainter_->SetColor(fadeColor_);
102 fadePainter_->PaintSide(context, viewPort, offset);
103 }
104 }
105
HandleOverScroll(Axis axis,double overScroll,const Size & viewPort)106 void ScrollFadeEffect::HandleOverScroll(Axis axis, double overScroll, const Size& viewPort)
107 {
108 if (NearZero(overScroll)) {
109 return;
110 }
111
112 SetPaintDirection(axis, overScroll);
113
114 if (!fadeController_) {
115 fadeController_ = AceType::MakeRefPtr<ScrollFadeController>(scroll_.Upgrade()->GetContext());
116 fadeController_->SetCallback([weakFade = AceType::WeakClaim(this)](double opacity, double scale) {
117 auto fade = weakFade.Upgrade();
118 if (fade) {
119 fade->SetOpacityAndScale(opacity, scale);
120 }
121 });
122 }
123
124 if (fadeController_ && scrollable_) {
125 double dragVelocity = scrollable_->GetCurrentVelocity();
126 if (!NearZero(dragVelocity)) {
127 fadeController_->ProcessAbsorb(std::abs(dragVelocity));
128 } else {
129 axis == Axis::VERTICAL
130 ? fadeController_->ProcessPull(std::abs(overScroll), viewPort.Height(), viewPort.Width())
131 : fadeController_->ProcessPull(std::abs(overScroll), viewPort.Width(), viewPort.Height());
132 }
133 }
134 }
135
SetOpacityAndScale(double opacity,double scale)136 void ScrollFadeEffect::SetOpacityAndScale(double opacity, double scale)
137 {
138 if (fadePainter_) {
139 fadePainter_->SetOpacity(opacity);
140 fadePainter_->SetScaleFactor(scale);
141
142 auto scroll = scroll_.Upgrade();
143 if (scroll) {
144 scroll->MarkNeedRender();
145 }
146 }
147 }
148
149 } // namespace OHOS::Ace