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