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/stepper/stepper_animation_controller.h"
17
18 #include "core/components/stepper/render_stepper.h"
19
20 namespace OHOS::Ace {
21 namespace {
22
23 constexpr double MAX_OPACITY = 255.0;
24 constexpr double MIN_OPACITY = 0.0;
25 constexpr int32_t FROM_INDEX_OPACITY_DURATION = 400;
26 constexpr int32_t TO_INDEX_OPACITY_DURATION = 700;
27
28 constexpr int32_t TRANSLATE_DURATION = 700;
29 constexpr double RATIO_NEGATIVE = -0.5;
30 constexpr double RATIO_ZERO = 0;
31 constexpr double RATIO_POSITIVE = 0.5;
32
UpdateStepperItemOpacity(const WeakPtr<StepperAnimationController> & weak,double value,bool isFromIndex)33 void UpdateStepperItemOpacity(const WeakPtr<StepperAnimationController>& weak, double value, bool isFromIndex)
34 {
35 auto animationController = weak.Upgrade();
36 if (!animationController) {
37 return;
38 }
39
40 auto stepper = animationController->GetRenderStepper().Upgrade();
41 if (!stepper) {
42 return;
43 }
44
45 auto renderStepper = AceType::DynamicCast<RenderStepper>(stepper);
46 if (!renderStepper) {
47 return;
48 }
49
50 auto curValue = (uint8_t)value;
51 if (isFromIndex) {
52 renderStepper->UpdateItemOpacity(curValue, renderStepper->GetFromIndex());
53 } else {
54 renderStepper->UpdateItemOpacity(curValue, renderStepper->GetToIndex());
55 }
56 }
57
UpdateStepperItemPosition(const WeakPtr<StepperAnimationController> & weak,double value,bool isFromIndex)58 void UpdateStepperItemPosition(const WeakPtr<StepperAnimationController>& weak, double value, bool isFromIndex)
59 {
60 auto animationController = weak.Upgrade();
61 if (!animationController) {
62 return;
63 }
64
65 auto stepper = animationController->GetRenderStepper().Upgrade();
66 if (!stepper) {
67 return;
68 }
69
70 auto renderStepper = AceType::DynamicCast<RenderStepper>(stepper);
71 if (!renderStepper) {
72 return;
73 }
74
75 auto curValue = value * renderStepper->GetStepperWidth();
76 if (isFromIndex) {
77 renderStepper->UpdateItemPosition(curValue, renderStepper->GetFromIndex());
78 } else {
79 renderStepper->UpdateItemPosition(curValue, renderStepper->GetToIndex());
80 }
81 }
82
83 } // namespace
84
StepperAnimation(const WeakPtr<PipelineContext> & context,double start,double end,int delay,int duration,const RefPtr<Curve> & curve,const AnimationCallback & callback)85 StepperAnimation::StepperAnimation(const WeakPtr<PipelineContext>& context, double start, double end, int delay,
86 int duration, const RefPtr<Curve>& curve, const AnimationCallback& callback)
87 : start_(start), end_(end), delay_(delay), duration_(duration)
88 {
89 curve_ = curve;
90 callback_ = callback;
91 context_ = context;
92 animation_ = AceType::MakeRefPtr<CurveAnimation<double>>(start_, end_, curve_);
93 animation_->AddListener(Animation<double>::ValueCallback(callback_));
94 controller_ = CREATE_ANIMATOR(context_);
95 controller_->SetDuration(duration_);
96 controller_->SetStartDelay(delay_);
97 }
98
Play()99 void StepperAnimation::Play()
100 {
101 if (!controller_ || !animation_) {
102 return;
103 }
104 controller_->ClearInterpolators();
105 controller_->AddInterpolator(animation_);
106 controller_->Play();
107 }
108
Stop()109 void StepperAnimation::Stop()
110 {
111 if (controller_) {
112 controller_->Finish();
113 }
114 }
115
CreateAnimation()116 void StepperAnimationController::CreateAnimation()
117 {
118 CreateOpacityAnimation();
119 CreateTranslateAnimation();
120 }
121
CreateOpacityAnimation()122 void StepperAnimationController::CreateOpacityAnimation()
123 {
124 auto weak = AceType::WeakClaim(this);
125 fromIndexOpacityAnimation_ = AceType::MakeRefPtr<StepperAnimation>(context_, MAX_OPACITY, MIN_OPACITY,
126 0, FROM_INDEX_OPACITY_DURATION, Curves::FRICTION, [weak](double value) {
127 UpdateStepperItemOpacity(weak, value, true);
128 });
129
130 toIndexOpacityAnimation_ = AceType::MakeRefPtr<StepperAnimation>(context_, MIN_OPACITY, MAX_OPACITY,
131 0, TO_INDEX_OPACITY_DURATION, Curves::SMOOTH, [weak](double value) {
132 UpdateStepperItemOpacity(weak, value, false);
133 });
134 }
135
CreateTranslateAnimation()136 void StepperAnimationController::CreateTranslateAnimation()
137 {
138 auto weak = AceType::WeakClaim(this);
139 fromIndexTranslateAnimationNext_ = AceType::MakeRefPtr<StepperAnimation>(context_, RATIO_ZERO,
140 RATIO_NEGATIVE, 0, TRANSLATE_DURATION, Curves::FRICTION, [weak](double value) {
141 UpdateStepperItemPosition(weak, value, true);
142 });
143
144 toIndexTranslateAnimationNext_ = AceType::MakeRefPtr<StepperAnimation>(context_, RATIO_POSITIVE,
145 RATIO_ZERO, 0, TRANSLATE_DURATION, Curves::FAST_OUT_SLOW_IN, [weak](double value) {
146 UpdateStepperItemPosition(weak, value, false);
147 });
148
149 fromIndexTranslateAnimationBack_ = AceType::MakeRefPtr<StepperAnimation>(context_, RATIO_ZERO,
150 RATIO_POSITIVE, 0, TRANSLATE_DURATION, Curves::FRICTION, [weak](double value) {
151 UpdateStepperItemPosition(weak, value, true);
152 });
153
154 toIndexTranslateAnimationBack_ = AceType::MakeRefPtr<StepperAnimation>(context_, RATIO_NEGATIVE,
155 RATIO_ZERO, 0, TRANSLATE_DURATION, Curves::FAST_OUT_SLOW_IN, [weak](double value) {
156 UpdateStepperItemPosition(weak, value, false);
157 });
158 }
159
PlayNextAnimation()160 void StepperAnimationController::PlayNextAnimation()
161 {
162 if (fromIndexOpacityAnimation_) {
163 fromIndexOpacityAnimation_->Play();
164 }
165 if (toIndexOpacityAnimation_) {
166 toIndexOpacityAnimation_->Play();
167 }
168 if (fromIndexTranslateAnimationNext_) {
169 fromIndexTranslateAnimationNext_->Play();
170 }
171 if (toIndexTranslateAnimationNext_) {
172 toIndexTranslateAnimationNext_->Play();
173 }
174 }
175
StopNextAnimation()176 void StepperAnimationController::StopNextAnimation()
177 {
178 if (fromIndexOpacityAnimation_) {
179 fromIndexOpacityAnimation_->Stop();
180 }
181 if (toIndexOpacityAnimation_) {
182 toIndexOpacityAnimation_->Stop();
183 }
184 if (fromIndexTranslateAnimationNext_) {
185 fromIndexTranslateAnimationNext_->Stop();
186 }
187 if (toIndexTranslateAnimationNext_) {
188 toIndexTranslateAnimationNext_->Stop();
189 }
190 }
191
PlayBackAnimation()192 void StepperAnimationController::PlayBackAnimation()
193 {
194 if (fromIndexOpacityAnimation_) {
195 fromIndexOpacityAnimation_->Play();
196 }
197 if (toIndexOpacityAnimation_) {
198 toIndexOpacityAnimation_->Play();
199 }
200 if (fromIndexTranslateAnimationBack_) {
201 fromIndexTranslateAnimationBack_->Play();
202 }
203 if (toIndexTranslateAnimationBack_) {
204 toIndexTranslateAnimationBack_->Play();
205 }
206 }
207
StopBackAnimation()208 void StepperAnimationController::StopBackAnimation()
209 {
210 if (fromIndexOpacityAnimation_) {
211 fromIndexOpacityAnimation_->Stop();
212 }
213 if (toIndexOpacityAnimation_) {
214 toIndexOpacityAnimation_->Stop();
215 }
216 if (fromIndexTranslateAnimationBack_) {
217 fromIndexTranslateAnimationBack_->Stop();
218 }
219 if (toIndexTranslateAnimationBack_) {
220 toIndexTranslateAnimationBack_->Stop();
221 }
222 }
223
PlayStepperToAnimation(int32_t fromIndex,int32_t toIndex,bool reverse)224 void StepperAnimationController::PlayStepperToAnimation(int32_t fromIndex, int32_t toIndex, bool reverse)
225 {
226 if (!isAnimationCreated_) {
227 CreateAnimation();
228 isAnimationCreated_ = true;
229 }
230
231 StopNextAnimation();
232 if (toIndexTranslateAnimationNext_) {
233 toIndexTranslateAnimationNext_->ClearStopListenerCallback();
234 }
235
236 StopBackAnimation();
237 if (toIndexTranslateAnimationBack_) {
238 toIndexTranslateAnimationBack_->ClearStopListenerCallback();
239 }
240
241 if (toIndex > fromIndex) {
242 if (toIndexTranslateAnimationNext_ && animationStopCallback_) {
243 toIndexTranslateAnimationNext_->AddStopListenerCallback(animationStopCallback_);
244 }
245 PlayNextAnimation();
246 } else {
247 if (toIndexTranslateAnimationBack_ && animationStopCallback_) {
248 toIndexTranslateAnimationBack_->AddStopListenerCallback(animationStopCallback_);
249 }
250 PlayBackAnimation();
251 }
252 }
253
254 } // namespace OHOS::Ace
255