• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_ng/pattern/swiper/arc_swiper_pattern.h"
17 
18 #include "base/perfmonitor/perf_constants.h"
19 #include "base/perfmonitor/perf_monitor.h"
20 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_pattern.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
24 constexpr float HORIZONTAL_EXIT_SCALE_FINAL_VALUE = 0.6f;
25 constexpr int32_t HORIZONTAL_EXIT_SCALE_DURATION = 750;
26 constexpr int32_t HORIZONTAL_EXIT_OFFSET_DURATION = 750;
27 constexpr int32_t HORIZONTAL_EXIT_BLUR_VALUE = 30;
28 constexpr int32_t HORIZONTAL_EXIT_BLUR_DELAY = 150;
29 constexpr int32_t HORIZONTAL_EXIT_BLUR_DURATION = 250;
30 constexpr int32_t HORIZONTAL_EXIT_ALPHA_DURATION = 750;
31 
32 constexpr float HORIZONTAL_ENTRY_SCALE_INITIAL_VALUE = 0.6f;
33 constexpr int32_t HORIZONTAL_ENTRY_SCALE_DURATION = 750;
34 constexpr int32_t HORIZONTAL_ENTRY_OFFSET_DURATION = 750;
35 constexpr int32_t HORIZONTAL_ENTRY_BLUR_VALUE = 30;
36 constexpr int32_t HORIZONTAL_ENTRY_BLUR_DURATION = 250;
37 constexpr int32_t HORIZONTAL_ENTRY_ALPHA_DURATION = 500;
38 
39 constexpr float VERTICAL_EXIT_SCALE_VALUE = 0.95f;
40 constexpr int32_t VERTICAL_EXIT_SCALE_DURATION = 250;
41 constexpr int32_t VERTICAL_EXIT_OFFSET_DURATION = 250;
42 constexpr int32_t VERTICAL_EXIT_BLUR_INITIAL_VALUE = 0;
43 constexpr int32_t VERTICAL_EXIT_BLUR_VALUE = 40;
44 constexpr int32_t VERTICAL_EXIT_BLUR_DURATION = 250;
45 constexpr int32_t VERTICAL_EXIT_ALPHA_DURATION = 250;
46 
47 constexpr float VERTICAL_ENTRY_SCALE_VALUE = 105.0f / 100.0f;
48 constexpr int32_t VERTICAL_ENTRY_SCALE_DELAY = 100;
49 constexpr int32_t VERTICAL_ENTRY_SCALE_DURATION = 270;
50 constexpr int32_t VERTICAL_ENTRY_OFFSET_DELAY = 100;
51 constexpr int32_t VERTICAL_ENTRY_OFFSET_DURATION = 270;
52 constexpr int32_t VERTICAL_ENTRY_ALPHA_DELAY = 100;
53 constexpr int32_t VERTICAL_ENTRY_ALPHA_DURATION = 270;
54 constexpr int32_t VERTICAL_ENTRY_COLOR_DURATION = 370;
55 
56 constexpr float HORIZONTAL_SCALE_REDUCTION_FACTOR = 0.4f;
57 constexpr float HORIZONTAL_BLUR_MIN_RATIO = 0.2f;
58 constexpr float HORIZONTAL_BLUR_REDUCTION_FACTOR = 750.0f / 250.0f * 30.0f;
59 constexpr float HORIZONTAL_BLUR_MAX_VALUE = 30.0f;
60 constexpr float HORIZONTAL_ALPHA_REDUCTION_FACTOR = 750.0f / 500.0f;
61 
62 constexpr float VERTICAL_EXIT_SCALE_REDUCTION_FACTOR = 466.0f / 2300.0f;
63 constexpr float VERTICAL_EXIT_SCALE_MIN_VALUE = 0.95f;
64 constexpr float VERTICAL_EXIT_BLUR_REDUCTION_FACTOR = 3728.0f  / 23.0f;
65 constexpr float VERTICAL_EXIT_BLUR_MAX_VALUE = 40.0f;
66 constexpr float VERTICAL_EXIT_OFFSET_PART = 115.0f / 466.0f;
67 constexpr float VERTICAL_EXIT_ALPHA_REDUCTION_FACTOR = 466.0f / 115.0f;
68 
69 constexpr float VERTICAL_ENTRY_OFFSET_PART = 0.6f;
70 constexpr float VERTICAL_ENTRY_SCALE_INITIAL_VALUE = 1.05f;
71 constexpr float VERTICAL_ENTRY_SCALE_REDUCTION_FACTOR = 0.125f;
72 constexpr float VERTICAL_ENTRY_BLUR_INITIAL_VALUE = 40.0f;
73 constexpr float VERTICAL_ENTRY_BLUR_REDUCTION_FACTOR = 100.0f;
74 constexpr float VERTICAL_ENTRY_BLUR_ALPHA_FACTOR = 2.5f;
75 
76 constexpr float DEFAULT_MINIMUM_AMPLITUDE_PX = 2.5f;
77 constexpr int32_t HALF = 2;
78 constexpr int32_t ANIMATION_SIZE = 8;
79 constexpr int32_t VERTICAL_ANIMATION_SIZE = 9;
80 constexpr int32_t NO_ANIMAION_DEFAULT_DURATION = 400;
81 constexpr int32_t VERTICAL_ANIMAION_DEFAULT_DURATION = 330;
82 constexpr int32_t HORIZONTAL_ANIMAION_DEFAULT_DURATION = 750;
83 #ifdef SUPPORT_DIGITAL_CROWN
84 constexpr const char* HAPTIC_STRENGTH3 = "watchhaptic.feedback.crown.strength3";
85 #endif
86 
GetHorizontalExitScaleValue(bool rollBack)87 float GetHorizontalExitScaleValue(bool rollBack)
88 {
89     return rollBack ? 1.0f : HORIZONTAL_EXIT_SCALE_FINAL_VALUE;
90 }
GetHorizontalExitBlurValue(bool rollBack)91 float GetHorizontalExitBlurValue(bool rollBack)
92 {
93     return rollBack ? 0.0f : HORIZONTAL_EXIT_BLUR_VALUE;
94 }
GetHorizontalExitAlphaValue(bool rollBack)95 float GetHorizontalExitAlphaValue(bool rollBack)
96 {
97     return rollBack ? 1.0f : 0.0f;
98 }
GetVerticalExitScaleValue(bool rollBack)99 float GetVerticalExitScaleValue(bool rollBack)
100 {
101     return rollBack ? 1.0f : VERTICAL_EXIT_SCALE_VALUE;
102 }
GetVerticalExitBlurValue(bool rollBack)103 float GetVerticalExitBlurValue(bool rollBack)
104 {
105     return rollBack ? 0.0f : VERTICAL_EXIT_BLUR_VALUE;
106 }
GetVerticalExitAlphaValue(bool rollBack)107 float GetVerticalExitAlphaValue(bool rollBack)
108 {
109     return rollBack ? 1.0f : 0.0f;
110 }
GetVerticalExitOffsetValue(bool rollBack,float offset)111 float GetVerticalExitOffsetValue(bool rollBack, float offset)
112 {
113     return rollBack ? offset : offset * VERTICAL_EXIT_OFFSET_PART;
114 }
GetVerticalEntryAlphaValue(bool rollBack)115 float GetVerticalEntryAlphaValue(bool rollBack)
116 {
117     return rollBack ? 0.0f : 1.0f;
118 }
119 #ifdef SUPPORT_DIGITAL_CROWN
120 constexpr int32_t MIN_TURN_PAGE_VELOCITY = 1200;
121 constexpr int32_t NEW_MIN_TURN_PAGE_VELOCITY = 780;
122 #endif
123 } // namespace name
SaveCircleDotIndicatorProperty(const RefPtr<FrameNode> & indicatorNode)124 void ArcSwiperPattern::SaveCircleDotIndicatorProperty(const RefPtr<FrameNode>& indicatorNode)
125 {
126     CHECK_NULL_VOID(indicatorNode);
127     auto indicatorPattern = indicatorNode->GetPattern<SwiperIndicatorPattern>();
128     CHECK_NULL_VOID(indicatorPattern);
129     auto layoutProperty = indicatorNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
130     CHECK_NULL_VOID(layoutProperty);
131     auto paintProperty = indicatorNode->GetPaintProperty<CircleDotIndicatorPaintProperty>();
132     CHECK_NULL_VOID(paintProperty);
133     auto pipelineContext = GetHost()->GetContext();
134     CHECK_NULL_VOID(pipelineContext);
135     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
136     CHECK_NULL_VOID(swiperIndicatorTheme);
137     auto swiperParameters = GetSwiperArcDotParameters();
138     CHECK_NULL_VOID(swiperParameters);
139     layoutProperty->ResetIndicatorLayoutStyle();
140     paintProperty->UpdateArcDirection(swiperParameters->arcDirection.value_or(SwiperArcDirection::SIX_CLOCK_DIRECTION));
141     paintProperty->UpdateColor(swiperParameters->itemColor.value_or(swiperIndicatorTheme->GetArcItemColor()));
142     paintProperty->UpdateSelectedColor(
143         swiperParameters->selectedItemColor.value_or(swiperIndicatorTheme->GetArcSelectedItemColor()));
144     paintProperty->UpdateContainerColor(
145         swiperParameters->containerColor.value_or(swiperIndicatorTheme->GetArcContainerColor()));
146     paintProperty->UpdateMaskColor(swiperParameters->maskColor.value_or(swiperIndicatorTheme->GetArcMaskColor()));
147     MarkDirtyNodeSelf();
148     indicatorNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
149 }
150 
SetSwiperArcDotParameters(const SwiperArcDotParameters & swiperArcDotParameters)151 void ArcSwiperPattern::SetSwiperArcDotParameters(const SwiperArcDotParameters& swiperArcDotParameters)
152 {
153     swiperArcDotParameters_ = std::make_shared<SwiperArcDotParameters>(swiperArcDotParameters);
154 }
155 
GetArcDotIndicatorStyle() const156 std::string ArcSwiperPattern::GetArcDotIndicatorStyle() const
157 {
158     auto swiperParameters = GetSwiperArcDotParameters();
159     CHECK_NULL_RETURN(swiperParameters, "");
160     auto jsonValue = JsonUtil::Create(true);
161     auto pipelineContext = GetHost()->GetContext();
162     CHECK_NULL_RETURN(pipelineContext, "");
163     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
164     CHECK_NULL_RETURN(swiperIndicatorTheme, "");
165 
166     static const char* ARC_DIRECTION[] = { "ArcDirection.THREE_CLOCK_DIRECTION", "ArcDirection.SIX_CLOCK_DIRECTION",
167         "ArcDirection.NINE_CLOCK_DIRECTION" };
168     jsonValue->Put("arcDirection", ARC_DIRECTION[static_cast<int32_t>(swiperParameters->arcDirection.value_or(
169         SwiperArcDirection::SIX_CLOCK_DIRECTION))]);
170     jsonValue->Put("itemColor",
171         swiperParameters->itemColor.value_or(swiperIndicatorTheme->GetArcItemColor()).ColorToString().c_str());
172     jsonValue->Put("selectedItemColor",
173         swiperParameters->selectedItemColor.value_or(swiperIndicatorTheme->GetArcSelectedItemColor())
174             .ColorToString()
175             .c_str());
176     jsonValue->Put(
177         "backgroundColor", swiperParameters->containerColor.value_or(swiperIndicatorTheme->GetArcContainerColor())
178             .ColorToString()
179             .c_str());
180     jsonValue->Put("maskColor",
181         GradientToJson(swiperParameters->maskColor.value_or(swiperIndicatorTheme->GetArcMaskColor())).c_str());
182 
183     return jsonValue->ToString();
184 }
185 
GetSwiperArcDotParameters() const186 std::shared_ptr<SwiperArcDotParameters> ArcSwiperPattern::GetSwiperArcDotParameters() const
187 {
188     if (swiperArcDotParameters_ == nullptr) {
189         swiperArcDotParameters_ = std::make_shared<SwiperArcDotParameters>();
190         auto pipelineContext = GetHost()->GetContext();
191         CHECK_NULL_RETURN(pipelineContext, swiperArcDotParameters_);
192         auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
193 
194         swiperArcDotParameters_->arcDirection = SwiperArcDirection::SIX_CLOCK_DIRECTION;
195         swiperArcDotParameters_->itemColor = swiperIndicatorTheme->GetArcItemColor();
196         swiperArcDotParameters_->selectedItemColor = swiperIndicatorTheme->GetArcSelectedItemColor();
197         swiperArcDotParameters_->containerColor = swiperIndicatorTheme->GetArcContainerColor();
198         swiperArcDotParameters_->maskColor = swiperIndicatorTheme->GetArcMaskColor();
199     }
200     return swiperArcDotParameters_;
201 }
202 
GradientToJson(Gradient colors) const203 std::string ArcSwiperPattern::GradientToJson(Gradient colors) const
204 {
205     auto jsonArray = JsonUtil::CreateArray(true);
206     for (size_t index = 0; index < colors.GetColors().size(); ++index) {
207         auto gradientColor = colors.GetColors()[index];
208         auto gradientColorJson = JsonUtil::Create(true);
209         gradientColorJson->Put("color", gradientColor.GetLinearColor().ToColor().ColorToString().c_str());
210         gradientColorJson->Put("offset", std::to_string(gradientColor.GetDimension().Value()).c_str());
211         jsonArray->Put(std::to_string(index).c_str(), gradientColorJson);
212     }
213     return jsonArray->ToString();
214 }
215 
SetDisableTransitionAnimation(bool isDisable)216 void ArcSwiperPattern::SetDisableTransitionAnimation(bool isDisable)
217 {
218     disableTransitionAnimation_ = isDisable;
219 }
220 
IsDisableTransitionAnimation() const221 bool ArcSwiperPattern::IsDisableTransitionAnimation() const
222 {
223     return disableTransitionAnimation_;
224 }
225 
PlayHorizontalAnimation(const OffsetF & offset,int32_t index,const RefPtr<FrameNode> & frameNode,bool rollBack)226 void ArcSwiperPattern::PlayHorizontalAnimation(const OffsetF& offset, int32_t index, const RefPtr<FrameNode>& frameNode,
227     bool rollBack)
228 {
229     auto isHorizontalAndRightToLeft = IsHorizontalAndRightToLeft();
230     if (IsPreItem(index, offset.GetX(), rollBack) && !isHorizontalAndRightToLeft) {
231         PlayHorizontalExitAnimation(offset, frameNode, rollBack && !isHorizontalAndRightToLeft);
232     } else {
233         PlayHorizontalEntryAnimation(offset, frameNode, rollBack && !isHorizontalAndRightToLeft);
234     }
235 }
236 
PlayVerticalAnimation(const OffsetF & offset,int32_t index,const RefPtr<FrameNode> & frameNode,bool rollBack)237 void ArcSwiperPattern::PlayVerticalAnimation(const OffsetF& offset, int32_t index, const RefPtr<FrameNode>& frameNode,
238     bool rollBack)
239 {
240     if (IsPreItem(index, offset.GetY(), rollBack)) {
241         PlayVerticalExitAnimation(offset, frameNode, rollBack);
242     } else {
243         PlayVerticalEntryAnimation(offset, frameNode, rollBack);
244     }
245 }
246 
IsPreItem(int32_t index,float translate,bool rollback)247 bool ArcSwiperPattern::IsPreItem(int32_t index, float translate, bool rollback)
248 {
249     if (IsHorizontalAndRightToLeft()) {
250         translate = -translate;
251     }
252     if (translate < 0) {
253         if (index < static_cast<int32_t>(itemPosition_.size() / HALF)) {
254             return !rollback;
255         } else {
256             return rollback;
257         }
258     } else {
259         if (index < static_cast<int32_t>(itemPosition_.size() / HALF)) {
260             return rollback;
261         } else {
262             return !rollback;
263         }
264     }
265 }
266 
BuildAnimationFinishCallback(bool exit,AnimationParam & param,const RefPtr<RenderContext> & renderContext,FinishCallback & finishCallback)267 void ArcSwiperPattern::BuildAnimationFinishCallback(bool exit, AnimationParam& param,
268     const RefPtr<RenderContext>& renderContext, FinishCallback& finishCallback)
269 {
270     BlurOption blurOption;
271     finishCallback = [weak = WeakClaim(this), param, blurOption,
272         weakRenderContext = WeakPtr<RenderContext>(renderContext), exit]() {
273         auto swiper = weak.Upgrade();
274         CHECK_NULL_VOID(swiper);
275         auto renderContext = weakRenderContext.Upgrade();
276         CHECK_NULL_VOID(renderContext);
277         if (param.type == AnimationType::TYPE_SCALE) {
278             if (exit) {
279                 swiper->AddFinishAnimation(AnimationFinishType::EXIT_SCALE);
280             } else {
281                 swiper->AddFinishAnimation(AnimationFinishType::ENTRY_SCALE);
282             }
283         } else if (param.type == AnimationType::TYPE_ALPHA) {
284             if (exit) {
285                 swiper->AddFinishAnimation(AnimationFinishType::EXIT_ALPHA);
286             } else {
287                 swiper->AddFinishAnimation(AnimationFinishType::ENTRY_ALPHA);
288             }
289         } else if (param.type == AnimationType::TYPE_BLUR) {
290             if (exit) {
291                 swiper->AddFinishAnimation(AnimationFinishType::EXIT_BLUR);
292             } else {
293                 swiper->AddFinishAnimation(AnimationFinishType::ENTRY_BLUR);
294             }
295         } else if (param.type == AnimationType::TYPE_OFFSET) {
296             if (exit) {
297                 swiper->AddFinishAnimation(AnimationFinishType::EXIT_OFFSET);
298             } else {
299                 swiper->AddFinishAnimation(AnimationFinishType::ENTRY_OFFSET);
300             }
301         } else if (param.type == AnimationType::TYPE_COLOR) {
302             if (exit) {
303                 swiper->AddFinishAnimation(AnimationFinishType::EXIT_BACKGROUND);
304             } else {
305                 swiper->AddFinishAnimation(AnimationFinishType::ENTRY_BACKGROUND);
306             }
307         }
308     };
309 }
310 
Animation(bool exit,AnimationParam & param,bool vertical,bool rollback)311 std::shared_ptr<AnimationUtils::Animation> ArcSwiperPattern::Animation(bool exit, AnimationParam& param, bool vertical,
312     bool rollback)
313 {
314     auto frameNode = param.frameNode;
315     BlurOption blurOption;
316     CHECK_NULL_RETURN(frameNode, nullptr);
317     auto renderContext = frameNode->GetRenderContext();
318     CHECK_NULL_RETURN(renderContext, nullptr);
319     FinishCallback finishCallback;
320     BuildAnimationFinishCallback(exit, param, renderContext, finishCallback);
321     auto propertyCallback = [param, blurOption, weakRenderContext = WeakPtr<RenderContext>(renderContext),
322         weakFrameNode = WeakPtr<FrameNode>(frameNode)]() {
323         auto renderContext = weakRenderContext.Upgrade();
324         CHECK_NULL_VOID(renderContext);
325         auto frameNode = weakFrameNode.Upgrade();
326         CHECK_NULL_VOID(frameNode);
327         if (param.type == AnimationType::TYPE_SCALE) {
328             renderContext->UpdateTransformScale({param.scaleValue, param.scaleValue});
329         } else if (param.type == AnimationType::TYPE_ALPHA) {
330             renderContext->UpdateOpacity(param.opacityValue);
331         } else if (param.type == AnimationType::TYPE_BLUR) {
332             renderContext->UpdateBackBlur(Dimension(param.blurValue, DimensionUnit::PERCENT), blurOption);
333         } else if (param.type == AnimationType::TYPE_COLOR) {
334             auto parentNode = frameNode->GetParentFrameNode();
335             CHECK_NULL_VOID(parentNode);
336             auto context = parentNode->GetRenderContext();
337             CHECK_NULL_VOID(context);
338             context->OnBackgroundColorUpdate(param.backColor);
339         } else if (param.type == AnimationType::TYPE_OFFSET) {
340             renderContext->UpdateTranslateInXY(param.offset);
341         }
342     };
343     return AnimationUtils::StartAnimation(
344         param.option, propertyCallback, finishCallback, nullptr /* repeatCallback */, frameNode->GetContextRefPtr());
345 }
346 
PlayHorizontalExitAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode,bool rollBack)347 void ArcSwiperPattern::PlayHorizontalExitAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode,
348     bool rollBack)
349 {
350     CHECK_NULL_VOID(frameNode);
351     auto renderContext = frameNode->GetRenderContext();
352     CHECK_NULL_VOID(renderContext);
353     // scale
354     AnimationParam scaleParam;
355     scaleParam.type = AnimationType::TYPE_SCALE;
356     scaleParam.frameNode = frameNode;
357     scaleParam.scaleValue = GetHorizontalExitScaleValue(rollBack);
358 
359     AnimationOption scaleOption;
360     scaleOption.SetDuration(CalcTime(HORIZONTAL_EXIT_SCALE_DURATION));
361     scaleOption.SetCurve(Curves::FRICTION);
362     scaleParam.option = scaleOption;
363     animationVector_.emplace_back(Animation(true, scaleParam));
364 
365     // offset
366     AnimationParam offsetParam;
367     offsetParam.type = AnimationType::TYPE_OFFSET;
368     offsetParam.frameNode = frameNode;
369     offsetParam.offset = offset;
370 
371     AnimationOption offsetOption;
372     offsetOption.SetDuration(CalcTime(HORIZONTAL_EXIT_OFFSET_DURATION));
373     offsetOption.SetCurve(Curves::FRICTION);
374     ElementRegister::GetInstance()->ReSyncGeometryTransition(GetHost(), offsetOption);
375     offsetParam.option = offsetOption;
376     animationVector_.emplace_back(Animation(true, offsetParam));
377 
378     // blur
379     AnimationParam blurParam;
380     blurParam.type = AnimationType::TYPE_BLUR;
381     blurParam.frameNode = frameNode;
382     blurParam.blurValue = GetHorizontalExitBlurValue(rollBack);
383 
384     AnimationOption blurAnimationOption;
385     blurAnimationOption.SetDelay(CalcTime(HORIZONTAL_EXIT_BLUR_DELAY));
386     blurAnimationOption.SetDuration(CalcTime(HORIZONTAL_EXIT_BLUR_DURATION));
387     blurAnimationOption.SetCurve(Curves::LINEAR);
388     blurParam.option = blurAnimationOption;
389     animationVector_.emplace_back(Animation(true, blurParam));
390 
391     // alpha
392     AnimationParam alphaParam;
393     alphaParam.type = AnimationType::TYPE_ALPHA;
394     alphaParam.frameNode = frameNode;
395     alphaParam.opacityValue = GetHorizontalExitAlphaValue(rollBack);
396 
397     AnimationOption alphaOption;
398     alphaOption.SetDuration(CalcTime(HORIZONTAL_EXIT_ALPHA_DURATION));
399     alphaOption.SetCurve(Curves::LINEAR);
400     alphaParam.option = alphaOption;
401     animationVector_.emplace_back(Animation(true, alphaParam));
402 }
403 
PlayHorizontalEntryAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode,bool rollback)404 void ArcSwiperPattern::PlayHorizontalEntryAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode,
405     bool rollback)
406 {
407     CHECK_NULL_VOID(frameNode);
408     auto renderContext = frameNode->GetRenderContext();
409     CHECK_NULL_VOID(renderContext);
410 
411     // scale
412     AnimationParam scaleParam;
413     scaleParam.type = AnimationType::TYPE_SCALE;
414     scaleParam.frameNode = frameNode;
415     scaleParam.scaleValue = GetHorizontalExitScaleValue(!rollback);
416 
417     AnimationOption scaleOption;
418     scaleOption.SetDuration(CalcTime(HORIZONTAL_ENTRY_SCALE_DURATION));
419     scaleOption.SetCurve(Curves::FRICTION);
420     scaleParam.option = scaleOption;
421     animationVector_.emplace_back(Animation(false, scaleParam));
422 
423     // offset
424     AnimationParam offsetParam;
425     offsetParam.type = AnimationType::TYPE_OFFSET;
426     offsetParam.frameNode = frameNode;
427     offsetParam.offset = offset;
428 
429     AnimationOption offsetOption;
430     offsetOption.SetDuration(CalcTime(HORIZONTAL_ENTRY_OFFSET_DURATION));
431     offsetOption.SetCurve(Curves::FRICTION);
432     ElementRegister::GetInstance()->ReSyncGeometryTransition(GetHost(), offsetOption);
433     offsetParam.option = offsetOption;
434     animationVector_.emplace_back(Animation(false, offsetParam));
435 
436     // blur
437     AnimationParam blurParam;
438     blurParam.type = AnimationType::TYPE_BLUR;
439     blurParam.frameNode = frameNode;
440     blurParam.blurValue = GetHorizontalExitBlurValue(!rollback);
441 
442     AnimationOption blurAnimationOption;
443     blurAnimationOption.SetDuration(CalcTime(HORIZONTAL_ENTRY_BLUR_DURATION));
444     blurAnimationOption.SetCurve(Curves::LINEAR);
445     blurParam.option = blurAnimationOption;
446     animationVector_.emplace_back(Animation(false, blurParam));
447     // alpha
448     AnimationParam alphaParam;
449     alphaParam.type = AnimationType::TYPE_ALPHA;
450     alphaParam.frameNode = frameNode;
451     alphaParam.opacityValue = GetHorizontalExitAlphaValue(!rollback);
452 
453     AnimationOption alphaOption;
454     alphaOption.SetDuration(CalcTime(HORIZONTAL_ENTRY_ALPHA_DURATION));
455     alphaOption.SetCurve(Curves::LINEAR);
456     alphaParam.option = alphaOption;
457     animationVector_.emplace_back(Animation(false, alphaParam));
458 }
459 
GetBackgroundColorValue(const RefPtr<FrameNode> & frameNode)460 std::shared_ptr<Color> ArcSwiperPattern::GetBackgroundColorValue(const RefPtr<FrameNode>& frameNode)
461 {
462     CHECK_NULL_RETURN(frameNode, nullptr);
463     auto context = frameNode->GetRenderContext();
464     CHECK_NULL_RETURN(context, nullptr);
465     auto color = context->GetBackgroundColor();
466     CHECK_NULL_RETURN(color, nullptr);
467     return std::make_shared<Color>(color.value());
468 }
469 
PlayVerticalExitOffsetAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode,bool rollBack)470 void ArcSwiperPattern::PlayVerticalExitOffsetAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode,
471     bool rollBack)
472 {
473     AnimationParam offsetParam;
474     offsetParam.type = AnimationType::TYPE_OFFSET;
475     offsetParam.frameNode = frameNode;
476 
477     auto offsetPart = GetVerticalExitOffsetValue(rollBack, offset.GetY());
478     offsetParam.offset.SetY(offsetPart);
479 
480     AnimationOption offsetOption;
481     offsetOption.SetDuration(CalcTime(VERTICAL_EXIT_OFFSET_DURATION));
482     offsetOption.SetCurve(Curves::FRICTION);
483     ElementRegister::GetInstance()->ReSyncGeometryTransition(GetHost(), offsetOption);
484     offsetParam.option = offsetOption;
485     animationVector_.emplace_back(Animation(true, offsetParam, true, rollBack));
486 }
487 
PlayVerticalExitAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode,bool rollBack)488 void ArcSwiperPattern::PlayVerticalExitAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode,
489     bool rollBack)
490 {
491     CHECK_NULL_VOID(frameNode);
492     auto renderContext = frameNode->GetRenderContext();
493     CHECK_NULL_VOID(renderContext);
494 
495     // scale
496     AnimationParam scaleParam;
497     scaleParam.type = AnimationType::TYPE_SCALE;
498     scaleParam.frameNode = frameNode;
499     scaleParam.scaleValue = GetVerticalExitScaleValue(rollBack);
500 
501     AnimationOption scaleOption;
502     scaleOption.SetDuration(CalcTime(VERTICAL_EXIT_SCALE_DURATION));
503     scaleOption.SetCurve(Curves::FRICTION);
504     scaleParam.option = scaleOption;
505     animationVector_.emplace_back(Animation(true, scaleParam, true, rollBack));
506 
507     // offset
508     PlayVerticalExitOffsetAnimation(offset, frameNode, rollBack);
509 
510     // blur
511     AnimationParam blurParam;
512     blurParam.type = AnimationType::TYPE_BLUR;
513     blurParam.frameNode = frameNode;
514     blurParam.blurValue = GetVerticalExitBlurValue(rollBack);
515 
516     AnimationOption blurAnimationOption;
517     blurAnimationOption.SetDuration(CalcTime(VERTICAL_EXIT_BLUR_DURATION));
518     blurAnimationOption.SetCurve(Curves::LINEAR);
519     blurParam.option = blurAnimationOption;
520     animationVector_.emplace_back(Animation(true, blurParam, true, rollBack));
521 
522     // alpha
523     AnimationParam alphaParam;
524     alphaParam.type = AnimationType::TYPE_ALPHA;
525     alphaParam.frameNode = frameNode;
526     alphaParam.opacityValue = GetVerticalExitAlphaValue(rollBack);
527 
528     AnimationOption alphaOption;
529     alphaOption.SetDuration(CalcTime(VERTICAL_EXIT_ALPHA_DURATION));
530     alphaOption.SetCurve(Curves::LINEAR);
531     alphaParam.option = alphaOption;
532     animationVector_.emplace_back(Animation(true, alphaParam, true, rollBack));
533 
534     // color
535     renderContext->OnBackgroundColorUpdate(Color::TRANSPARENT);
536 }
537 
GetEntryNodeBackgroundColor(const RefPtr<FrameNode> & frameNode)538 std::shared_ptr<Color> ArcSwiperPattern::GetEntryNodeBackgroundColor(const RefPtr<FrameNode>& frameNode)
539 {
540     // color
541     std::shared_ptr<Color> colorPtr = nullptr;
542     CHECK_NULL_RETURN(frameNode, colorPtr);
543     colorPtr = GetBackgroundColorValue(frameNode);
544     if (!colorPtr || *colorPtr == Color::TRANSPARENT) {
545         colorPtr = parentNodeBackgroundColor_;
546     }
547     if (colorPtr == nullptr) {
548         colorPtr = std::make_shared<Color>(Color::TRANSPARENT);
549     }
550     return colorPtr;
551 }
552 
GetVerticalEntryBackgroundValue(bool rollBack)553 Color ArcSwiperPattern::GetVerticalEntryBackgroundValue(bool rollBack)
554 {
555     Color color = Color::TRANSPARENT;
556     if (rollBack) {
557         if (preNodeBackgroundColor_ && *preNodeBackgroundColor_ != Color::TRANSPARENT) {
558             color = *preNodeBackgroundColor_;
559         } else if (parentNodeBackgroundColor_) {
560             color = *parentNodeBackgroundColor_;
561         }
562     } else {
563         if (entryNodeBackgroundColor_ && *entryNodeBackgroundColor_ != Color::TRANSPARENT) {
564             color = *entryNodeBackgroundColor_;
565         } else if (parentNodeBackgroundColor_) {
566             color = *parentNodeBackgroundColor_;
567         }
568     }
569     return color;
570 }
571 
PlayVerticalEntryOffsetAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode,bool rollBack)572 void ArcSwiperPattern::PlayVerticalEntryOffsetAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode,
573     bool rollBack)
574 {
575     if (!rollBack) {
576         // offset1: When alpha is 0, move to the starting point of the animation effect.
577         AnimationParam offsetParam1;
578         offsetParam1.type = AnimationType::TYPE_OFFSET;
579         offsetParam1.frameNode = frameNode;
580         auto offsetPart1 = offset.GetY() * VERTICAL_ENTRY_OFFSET_PART;
581         OffsetF offset1;
582         offset1.SetY(offsetPart1);
583         offsetParam1.offset = offset1;
584 
585         AnimationOption offsetOption1;
586         offsetOption1.SetDuration(CalcTime(VERTICAL_ENTRY_OFFSET_DELAY));
587         offsetOption1.SetCurve(Curves::FRICTION);
588         offsetParam1.option = offsetOption1;
589         animationVector_.emplace_back(Animation(false, offsetParam1));
590     }
591 
592     // offset2: Move to target position
593     AnimationParam offsetParam2;
594     offsetParam2.type = AnimationType::TYPE_OFFSET;
595     offsetParam2.frameNode = frameNode;
596     auto offsetPart2 = offset.GetY();
597     OffsetF offset2;
598     offset2.SetY(offsetPart2);
599     offsetParam2.offset = offset2;
600 
601     AnimationOption offsetOption2;
602     offsetOption2.SetDelay(CalcTime(VERTICAL_ENTRY_OFFSET_DELAY));
603     offsetOption2.SetDuration(CalcTime(VERTICAL_ENTRY_OFFSET_DURATION));
604     offsetOption2.SetCurve(Curves::FRICTION);
605     ElementRegister::GetInstance()->ReSyncGeometryTransition(GetHost(), offsetOption2);
606     offsetParam2.option = offsetOption2;
607     animationVector_.emplace_back(Animation(false, offsetParam2));
608 }
609 
PlayVerticalEntryBlurAnimation(const RefPtr<FrameNode> & frameNode,bool rollBack)610 void ArcSwiperPattern::PlayVerticalEntryBlurAnimation(const RefPtr<FrameNode>& frameNode, bool rollBack)
611 {
612     CHECK_NULL_VOID(frameNode);
613     if (rollBack) {
614         AnimationParam blurParam;
615         blurParam.type = AnimationType::TYPE_BLUR;
616         blurParam.frameNode = frameNode;
617         blurParam.blurValue = GetVerticalExitBlurValue(rollBack);
618 
619         AnimationOption blurAnimationOption;
620         blurAnimationOption.SetDuration(CalcTime(VERTICAL_EXIT_BLUR_DURATION));
621         blurAnimationOption.SetCurve(Curves::LINEAR);
622         blurParam.option = blurAnimationOption;
623         animationVector_.emplace_back(Animation(true, blurParam, true, rollBack));
624     } else {
625         BlurOption blurOption;
626         frameNode->GetRenderContext()->UpdateBackBlur(Dimension(0, DimensionUnit::PERCENT), blurOption);
627     }
628 }
629 
PlayVerticalEntryAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode,bool rollBack)630 void ArcSwiperPattern::PlayVerticalEntryAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode,
631     bool rollBack)
632 {
633     CHECK_NULL_VOID(frameNode);
634     auto renderContext = frameNode->GetRenderContext();
635     CHECK_NULL_VOID(renderContext);
636 
637     // scale
638     AnimationParam scaleParam;
639     scaleParam.type = AnimationType::TYPE_SCALE;
640     scaleParam.frameNode = frameNode;
641     scaleParam.scaleValue = 1.0f;
642 
643     AnimationOption scaleOption;
644     scaleOption.SetDelay(CalcTime(VERTICAL_ENTRY_SCALE_DELAY));
645     scaleOption.SetDuration(CalcTime(VERTICAL_ENTRY_SCALE_DURATION));
646     scaleOption.SetCurve(Curves::FRICTION);
647     scaleParam.option = scaleOption;
648     animationVector_.emplace_back(Animation(false, scaleParam, true, rollBack));
649 
650     // offset
651     PlayVerticalEntryOffsetAnimation(offset, frameNode, rollBack);
652 
653     // alpha
654     AnimationParam alphaParam;
655     alphaParam.type = AnimationType::TYPE_ALPHA;
656     alphaParam.frameNode = frameNode;
657     alphaParam.opacityValue = GetVerticalEntryAlphaValue(rollBack);
658 
659     AnimationOption alphaOption;
660     alphaOption.SetDelay(CalcTime(VERTICAL_ENTRY_ALPHA_DELAY));
661     alphaOption.SetDuration(CalcTime(VERTICAL_ENTRY_ALPHA_DURATION));
662     alphaOption.SetCurve(Curves::LINEAR);
663     alphaParam.option = alphaOption;
664     animationVector_.emplace_back(Animation(false, alphaParam));
665 
666     // color
667     entryNodeBackgroundColor_ = GetEntryNodeBackgroundColor(frameNode);
668     CHECK_NULL_VOID(entryNodeBackgroundColor_);
669     AnimationParam colorParam;
670     colorParam.type = AnimationType::TYPE_COLOR;
671 
672     colorParam.frameNode = frameNode;
673     colorParam.backColor = GetVerticalEntryBackgroundValue(rollBack);
674 
675     AnimationOption colorOption;
676     colorOption.SetDuration(CalcTime(VERTICAL_ENTRY_COLOR_DURATION));
677     colorOption.SetCurve(Curves::LINEAR);
678     colorParam.option = colorOption;
679     animationVector_.emplace_back(Animation(false, colorParam));
680 
681     //blur
682     PlayVerticalEntryBlurAnimation(frameNode, rollBack);
683 }
684 
IsScrollOverCritical()685 bool ArcSwiperPattern::IsScrollOverCritical()
686 {
687     if (targetIndex_ && targetIndex_.value() == currentIndex_) {
688         return false;
689     }
690     return true;
691 }
692 
PlayAnimation(const OffsetF & offset,int32_t index,const RefPtr<FrameNode> & frameNode)693 void ArcSwiperPattern::PlayAnimation(const OffsetF& offset, int32_t index, const RefPtr<FrameNode>& frameNode)
694 {
695     PerfMonitor::GetPerfMonitor()->Start(PerfConstants::APP_SWIPER_FLING, PerfActionType::FIRST_MOVE, "");
696     if (GetDirection() == Axis::HORIZONTAL) {
697         PlayHorizontalAnimation(offset, index, frameNode, !IsScrollOverCritical());
698     } else {
699         PlayVerticalAnimation(offset, index, frameNode, !IsScrollOverCritical());
700     }
701 }
702 
ClearAnimationFinishList()703 void ArcSwiperPattern::ClearAnimationFinishList()
704 {
705     animationFinishList_.clear();
706 }
707 
AnimationFinish()708 void ArcSwiperPattern::AnimationFinish()
709 {
710     if (!hasTabsAncestor_) {
711         PerfMonitor::GetPerfMonitor()->End(PerfConstants::APP_SWIPER_FLING, true);
712     }
713     OnPropertyTranslateAnimationFinish(offset_);
714 }
715 
PlayPropertyTranslateFlipAnimation(const OffsetF & offset)716 void ArcSwiperPattern::PlayPropertyTranslateFlipAnimation(const OffsetF& offset)
717 {
718     offset_ = offset;
719     auto adOffset = offset;
720     if (IsHorizontalAndRightToLeft()) {
721         if (GetDirection() == Axis::HORIZONTAL) {
722             adOffset.SetX(-adOffset.GetX());
723         } else {
724             adOffset.SetY(-adOffset.GetY());
725         }
726     }
727     int32_t index = 0;
728     if (!hasTabsAncestor_) {
729         PerfMonitor::GetPerfMonitor()->Start(PerfConstants::APP_SWIPER_FLING, PerfActionType::FIRST_MOVE, "");
730     }
731     for (auto &item : itemPosition_) {
732         auto frameNode = item.second.node;
733         if (frameNode) {
734             PlayAnimation(adOffset, index, frameNode);
735             index++;
736             item.second.finalOffset = adOffset;
737         }
738     }
739     itemPositionInAnimation_ = itemPosition_;
740 }
741 
InitialFrameNodePropertyAnimation(const OffsetF & offset,const RefPtr<FrameNode> & frameNode)742 void ArcSwiperPattern::InitialFrameNodePropertyAnimation(const OffsetF& offset, const RefPtr<FrameNode>& frameNode)
743 {
744     CHECK_NULL_VOID(frameNode);
745     for (auto animaiton: animationVector_) {
746         AnimationUtils::StopAnimation(animaiton);
747     }
748     animationVector_.clear();
749     frameNode->GetRenderContext()->UpdateTranslateInXY(offset);
750 }
751 
AddFinishAnimation(const AnimationFinishType & animationFinishType,bool vertical,bool rollBack)752 void ArcSwiperPattern::AddFinishAnimation(const AnimationFinishType& animationFinishType, bool vertical, bool rollBack)
753 {
754     animationFinishList_.emplace_back(animationFinishType);
755     if (vertical && !rollBack && animationFinishList_.size() == VERTICAL_ANIMATION_SIZE) {
756         AnimationFinish();
757     } else {
758         if (animationFinishList_.size() == ANIMATION_SIZE) {
759             AnimationFinish();
760         }
761     }
762 }
763 
HandlePropertyTranslateCallback(float translate,int32_t nextIndex,float velocity)764 void ArcSwiperPattern::HandlePropertyTranslateCallback(float translate, int32_t nextIndex, float velocity)
765 {
766     AnimationCallbackInfo info;
767     info.velocity = Dimension(velocity, DimensionUnit::PX).ConvertToVp();
768     info.currentOffset = GetCustomPropertyOffset() +
769         Dimension(currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
770     info.targetOffset = GetCustomPropertyTargetOffset() - Dimension(translate, DimensionUnit::PX).ConvertToVp();
771     if (IsHorizontalAndRightToLeft()) {
772         info.currentOffset =
773             GetCustomPropertyOffset() + Dimension(-currentIndexOffset_, DimensionUnit::PX).ConvertToVp();
774     }
775 
776     auto pipeline = PipelineContext::GetCurrentContext();
777     if (pipeline) {
778         pipeline->AddAfterRenderTask([weak = WeakClaim(this), info, nextIndex = GetLoopIndex(nextIndex)]() {
779             auto swiper = weak.Upgrade();
780             CHECK_NULL_VOID(swiper);
781             swiper->FireAnimationStartEvent(swiper->GetLoopIndex(swiper->currentIndex_), nextIndex, info);
782             swiper->FireAndCleanScrollingListener();
783         });
784     }
785 }
786 
BuildDefaultTranslateAnimationOption(AnimationOption & option,float translate)787 void ArcSwiperPattern::BuildDefaultTranslateAnimationOption(AnimationOption& option, float translate)
788 {
789     option.SetDuration(GetDuration());
790     auto iter = frameRateRange_.find(SwiperDynamicSyncSceneType::ANIMATE);
791     if (iter  != frameRateRange_.end()) {
792         option.SetFrameRateRange(iter->second);
793     }
794     auto curve = GetCurveIncludeMotion();
795     float minimumAmplitudeRatio = 0.0f;
796     if (translate != 0) {
797         minimumAmplitudeRatio = DEFAULT_MINIMUM_AMPLITUDE_PX / translate;
798     }
799     if (InstanceOf<InterpolatingSpring>(curve) &&
800         LessNotEqualCustomPrecision(
801             minimumAmplitudeRatio, InterpolatingSpring::DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO)) {
802         auto interpolatingSpring = AceType::DynamicCast<InterpolatingSpring>(curve);
803         interpolatingSpring->UpdateMinimumAmplitudeRatio(minimumAmplitudeRatio);
804     }
805     option.SetCurve(curve);
806     option.SetFinishCallbackType(GetFinishCallbackType());
807 }
808 
PlayPropertyTranslateDefaultAnimation(const OffsetF & offset,float translate)809 void ArcSwiperPattern::PlayPropertyTranslateDefaultAnimation(const OffsetF& offset, float translate)
810 {
811     auto adOffset = offset;
812     if (IsHorizontalAndRightToLeft()) {
813         if (GetDirection() == Axis::HORIZONTAL) {
814             adOffset.SetX(-adOffset.GetX());
815         } else {
816             adOffset.SetY(-adOffset.GetY());
817         }
818     }
819     AnimationOption option;
820     BuildDefaultTranslateAnimationOption(option, translate);
821     auto finishCallback = [weak = WeakClaim(this), offset]() {
822         auto swiper = weak.Upgrade();
823         CHECK_NULL_VOID(swiper);
824         if (!swiper->hasTabsAncestor_) {
825             PerfMonitor::GetPerfMonitor()->End(PerfConstants::APP_SWIPER_FLING, true);
826         }
827         OffsetF finalOffset =
828             swiper->itemPosition_.empty() ? OffsetF() : swiper->itemPosition_.begin()->second.node
829                 ? swiper->itemPosition_.begin()->second.node->GetRenderContext()->GetTranslateXYProperty() : OffsetF();
830         TAG_LOGI(AceLogTag::ACE_SWIPER,
831             "ArcSwiper finish property translate animation with offsetX: %{public}f, offsetY: %{public}f",
832             finalOffset.GetX(), finalOffset.GetY());
833         ACE_SCOPED_TRACE("ArcSwiper finish property animation X: %f, Y: %f", finalOffset.GetX(), finalOffset.GetY());
834         swiper->targetIndex_.reset();
835         swiper->OnPropertyTranslateAnimationFinish(offset);
836     };
837 
838     // property callback will call immediately.
839     auto propertyUpdateCallback = [swiper = WeakClaim(this), offset = adOffset]() {
840         auto swiperPattern = swiper.Upgrade();
841         CHECK_NULL_VOID(swiperPattern);
842         if (!swiperPattern->hasTabsAncestor_) {
843             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::APP_SWIPER_FLING, PerfActionType::FIRST_MOVE, "");
844         }
845         TAG_LOGI(AceLogTag::ACE_SWIPER,
846             "ArcSwiper start property translate animation with offsetX: %{public}f, offsetY: %{public}f", offset.GetX(),
847             offset.GetY());
848         ACE_SCOPED_TRACE("ArcSwiper start property animation, X: %f, Y: %f", offset.GetX(), offset.GetY());
849         for (auto& item : swiperPattern->itemPosition_) {
850             auto frameNode = item.second.node;
851             if (frameNode) {
852                 frameNode->GetRenderContext()->UpdateTranslateInXY(offset);
853                 item.second.finalOffset = offset;
854             }
855         }
856         swiperPattern->itemPositionInAnimation_ = swiperPattern->itemPosition_;
857     };
858     ElementRegister::GetInstance()->ReSyncGeometryTransition(GetHost(), option);
859     auto host = GetHost();
860     CHECK_NULL_VOID(host);
861     AnimationUtils::Animate(
862         option, propertyUpdateCallback, finishCallback, nullptr /* repeatCallback */, host->GetContextRefPtr());
863 }
864 
UsePropertyAnimation(const OffsetF & offset)865 void ArcSwiperPattern::UsePropertyAnimation(const OffsetF& offset)
866 {
867     if (GetPropertyAnimationIsRunning()) {
868         if (!NeedStartNewAnimation(offset)) {
869             stopIndicatorAnimation_ = false;
870             return;
871         }
872         std::optional<int32_t> targetIndex;
873         if (targetIndex_) {
874             targetIndex = targetIndex_;
875         }
876         StopPropertyTranslateAnimation(isFinishAnimation_);
877         StopIndicatorAnimation();
878 
879         if (targetIndex) {
880             targetIndex_ = targetIndex;
881             MarkDirtyNodeSelf();
882             return;
883         }
884     }
885 }
886 
PlayPropertyTranslateAnimation(float translate,int32_t nextIndex,float velocity,bool stopAutoPlay,std::optional<float> pixelRoundTargetPos)887 void ArcSwiperPattern::PlayPropertyTranslateAnimation(
888     float translate, int32_t nextIndex, float velocity, bool stopAutoPlay, std::optional<float> pixelRoundTargetPos)
889 {
890     if (NearZero(translate)) {
891         OnAnimationTranslateZero(nextIndex, stopAutoPlay);
892         return;
893     }
894 
895     if (translate != 0) {
896         motionVelocity_ = velocity / translate;
897     }
898 
899     OffsetF offset;
900     if (GetDirection() == Axis::HORIZONTAL) {
901         offset.AddX(translate);
902     } else {
903         offset.AddY(translate);
904     }
905     UsePropertyAnimation(offset);
906     ClearAnimationFinishList();
907     // initial translate info.
908     for (auto& item : itemPosition_) {
909         auto frameNode = item.second.node;
910         if (frameNode) {
911             InitialFrameNodePropertyAnimation(item.second.finalOffset, frameNode);
912         }
913     }
914 
915     SetPropertyAnimationIsRunning(true);
916     propertyAnimationIndex_ = nextIndex;
917     if (EnableTransitionAnimation()) {
918         PlayPropertyTranslateFlipAnimation(offset);
919     } else {
920         PlayPropertyTranslateDefaultAnimation(offset, translate);
921     }
922 
923     HandlePropertyTranslateCallback(translate, nextIndex, velocity);
924 
925     // enable lazy load feature.
926     SetLazyLoadFeature(true);
927     UpdateItemRenderGroup(true);
928 }
929 
IsLoop() const930 bool ArcSwiperPattern::IsLoop() const
931 {
932     return false;
933 }
934 
SetBackgroundColor(const RefPtr<RenderContext> & renderContext,const std::shared_ptr<Color> & color)935 void ArcSwiperPattern::SetBackgroundColor(const RefPtr<RenderContext>& renderContext,
936     const std::shared_ptr<Color>& color)
937 {
938     CHECK_NULL_VOID(renderContext);
939     if (color) {
940         renderContext->OnBackgroundColorUpdate(*color);
941     } else {
942         renderContext->OnBackgroundColorUpdate(Color::TRANSPARENT);
943     }
944 }
945 
PlayScrollBackgroundAnimation(const std::shared_ptr<Color> & color,const std::shared_ptr<Color> & parentColor,const RefPtr<RenderContext> & parentRenderContext,bool exitNodeNeedTransparent)946 void ArcSwiperPattern::PlayScrollBackgroundAnimation(const std::shared_ptr<Color>& color,
947     const std::shared_ptr<Color>& parentColor, const RefPtr<RenderContext>& parentRenderContext,
948     bool exitNodeNeedTransparent)
949 {
950     CHECK_NULL_VOID(parentRenderContext);
951     if (exitNodeNeedTransparent) {
952         auto exitFrameNode = exitFrameNode_.Upgrade();
953         CHECK_NULL_VOID(exitFrameNode);
954         auto exitRenderContext = exitFrameNode->GetRenderContext();
955         CHECK_NULL_VOID(exitRenderContext);
956         exitRenderContext->OnBackgroundColorUpdate(Color::TRANSPARENT);
957         CHECK_NULL_VOID(parentRenderContext);
958         if (color && (*color != Color::TRANSPARENT)) {
959             parentRenderContext->OnBackgroundColorUpdate(*color);
960         } else {
961             SetBackgroundColor(parentRenderContext, parentColor);
962         }
963     } else {
964         CHECK_NULL_VOID(parentRenderContext);
965         if (color && (*color != Color::TRANSPARENT)) {
966             parentRenderContext->OnBackgroundColorUpdate(*color);
967         } else {
968             SetBackgroundColor(parentRenderContext, parentColor);
969         }
970     }
971 }
972 
PlayHorizontalScrollExitAnimation(float swiperWidth,float startPos,const RefPtr<FrameNode> & frameNode)973 void ArcSwiperPattern::PlayHorizontalScrollExitAnimation(float swiperWidth, float startPos,
974     const RefPtr<FrameNode>& frameNode)
975 {
976     CHECK_NULL_VOID(frameNode);
977     auto curContext = frameNode->GetRenderContext();
978     CHECK_NULL_VOID(curContext);
979     if (swiperWidth == 0) {
980         return;
981     }
982     auto exitNodePercent = std::abs(startPos) / swiperWidth;
983     // scale
984     horizontalExitNodeScale_ = 1.0f - exitNodePercent * HORIZONTAL_SCALE_REDUCTION_FACTOR;
985     if (horizontalExitNodeScale_ < HORIZONTAL_EXIT_SCALE_FINAL_VALUE) {
986         horizontalExitNodeScale_ = HORIZONTAL_EXIT_SCALE_FINAL_VALUE;
987     }
988     curContext->UpdateTransformScale({horizontalExitNodeScale_, horizontalExitNodeScale_});
989 
990     // blur
991     if (exitNodePercent > HORIZONTAL_BLUR_MIN_RATIO) {
992         horizontalExitNodeBlur_ = HORIZONTAL_BLUR_REDUCTION_FACTOR * exitNodePercent;
993         if (horizontalExitNodeBlur_ > HORIZONTAL_BLUR_MAX_VALUE) {
994             horizontalExitNodeBlur_ = HORIZONTAL_BLUR_MAX_VALUE;
995         }
996         BlurOption blurOption;
997         curContext->UpdateBackBlur(Dimension(horizontalExitNodeBlur_, DimensionUnit::PERCENT), blurOption);
998     }
999 
1000     // alpha
1001     horizontalExitNodeOpacity_ = 1.0f - exitNodePercent;
1002     if (horizontalExitNodeOpacity_ < 0.0f) {
1003         horizontalExitNodeOpacity_ = 0.0f;
1004     }
1005     curContext->UpdateOpacity(horizontalExitNodeOpacity_);
1006 }
1007 
PlayHorizontalScrollEntryAnimation(float swiperWidth,float startPos,const RefPtr<FrameNode> & frameNode)1008 void ArcSwiperPattern::PlayHorizontalScrollEntryAnimation(float swiperWidth, float startPos,
1009     const RefPtr<FrameNode>& frameNode)
1010 {
1011     CHECK_NULL_VOID(frameNode);
1012     auto entryNodeContext = frameNode->GetRenderContext();
1013     CHECK_NULL_VOID(entryNodeContext);
1014     if (swiperWidth == 0) {
1015         return;
1016     }
1017     auto entryNodePercent = (swiperWidth - std::abs(startPos)) / swiperWidth;
1018     // scale
1019     horizontalEntryNodeScale_ = HORIZONTAL_ENTRY_SCALE_INITIAL_VALUE +
1020         HORIZONTAL_SCALE_REDUCTION_FACTOR * entryNodePercent;
1021     if (horizontalEntryNodeScale_ >= 1.0f) {
1022         horizontalEntryNodeScale_ = 1.0f;
1023     }
1024     entryNodeContext->UpdateTransformScale({horizontalEntryNodeScale_, horizontalEntryNodeScale_});
1025 
1026     // blur
1027     horizontalEntryNodeBlur_ = HORIZONTAL_BLUR_MAX_VALUE - HORIZONTAL_BLUR_REDUCTION_FACTOR * entryNodePercent;
1028     if (horizontalEntryNodeBlur_ < 0.0f) {
1029         horizontalEntryNodeBlur_ = 0.0f;
1030     }
1031     BlurOption blurOption;
1032     entryNodeContext->UpdateBackBlur(Dimension(horizontalEntryNodeBlur_, DimensionUnit::PERCENT), blurOption);
1033 
1034     // alpha
1035     horizontalEntryNodeOpacity_ = HORIZONTAL_ALPHA_REDUCTION_FACTOR * entryNodePercent;
1036     if (horizontalEntryNodeOpacity_ > 1.0f) {
1037         horizontalEntryNodeOpacity_ = 1.0f;
1038     }
1039     entryNodeContext->UpdateOpacity(horizontalEntryNodeOpacity_);
1040 }
1041 
HorizontalScrollAnimation(float offset)1042 void ArcSwiperPattern::HorizontalScrollAnimation(float offset)
1043 {
1044     if (canChangeDirectionFlag_) {
1045         scrollToLeft_ = (offset < 0) ? true : false;
1046     }
1047     auto swiperWidth = CalculateVisibleSize();
1048     std::map<int32_t, SwiperItemInfo>::iterator curInter;
1049     std::map<int32_t, SwiperItemInfo>::iterator nextInter;
1050     if (scrollToLeft_) {
1051         curInter = itemPosition_.begin();
1052         nextInter = std::next(curInter, 1);
1053         swiperProportion_ = TO_LEFT_ARC_SWIPER_PROPORTION;
1054     } else {
1055         nextInter = itemPosition_.begin();
1056         curInter = std::next(nextInter, 1);
1057         swiperProportion_ = TO_RIGHT_ARC_SWIPER_PROPORTION;
1058     }
1059     if (curInter != itemPosition_.end()) {
1060         auto curStartPos = curInter->second.startPos;
1061         auto curFrameNode = curInter->second.node;
1062         CHECK_NULL_VOID(curFrameNode);
1063         PlayHorizontalScrollExitAnimation(swiperWidth, curStartPos, curFrameNode);
1064     }
1065 
1066     if (nextInter != itemPosition_.end()) {
1067         auto nextStartPos = nextInter->second.startPos;
1068         auto nextFrameNode = nextInter->second.node;
1069         CHECK_NULL_VOID(nextFrameNode);
1070         PlayHorizontalScrollEntryAnimation(swiperWidth, nextStartPos, nextFrameNode);
1071     }
1072 }
1073 
VerticalScrollAnimation(float offset)1074 void ArcSwiperPattern::VerticalScrollAnimation(float offset)
1075 {
1076     if (canChangeDirectionFlag_) {
1077         scrollToTop_ = (offset < 0) ? true : false;
1078     }
1079     auto swiperWidth = CalculateVisibleSize();
1080     std::map<int32_t, SwiperItemInfo>::iterator curInter;
1081     std::map<int32_t, SwiperItemInfo>::iterator nextInter;
1082     if (scrollToTop_) {
1083         curInter = itemPosition_.begin();
1084         nextInter = std::next(curInter, 1);
1085         swiperProportion_ = TO_LEFT_ARC_SWIPER_PROPORTION;
1086     } else {
1087         nextInter = itemPosition_.begin();
1088         curInter = std::next(nextInter, 1);
1089         swiperProportion_ = TO_RIGHT_ARC_SWIPER_PROPORTION;
1090     }
1091     if (curInter != itemPosition_.end()) {
1092         auto curStartPos = curInter->second.startPos;
1093         auto curFrameNode = curInter->second.node;
1094         CHECK_NULL_VOID(curFrameNode);
1095         PlayVerticalScrollExitAnimation(swiperWidth, curStartPos, curFrameNode);
1096     }
1097 
1098     if (nextInter != itemPosition_.end()) {
1099         auto nextStartPos = nextInter->second.startPos;
1100         auto nextFrameNode = nextInter->second.node;
1101         CHECK_NULL_VOID(nextFrameNode);
1102         PlayVerticalScrollEntryAnimation(swiperWidth, nextStartPos, nextFrameNode);
1103     }
1104 }
1105 
PlayVerticalScrollExitAnimation(float swiperWidth,float startPos,const RefPtr<FrameNode> & frameNode)1106 void ArcSwiperPattern::PlayVerticalScrollExitAnimation(float swiperWidth, float startPos,
1107     const RefPtr<FrameNode>& frameNode)
1108 {
1109     CHECK_NULL_VOID(frameNode);
1110     exitFrameNode_ = WeakPtr<FrameNode>(frameNode);
1111     auto curNodeContext = frameNode->GetRenderContext();
1112     CHECK_NULL_VOID(curNodeContext);
1113     if (swiperWidth == 0) {
1114         return;
1115     }
1116     auto exitNodePercent = std::abs(startPos) / swiperWidth;
1117     // color
1118     preNodeBackgroundColor_ = GetBackgroundColorValue(frameNode);
1119     curNodeContext->OnBackgroundColorUpdate(Color::TRANSPARENT);
1120     // scale
1121     verticalExitNodeScale_ = 1.0f -  exitNodePercent * VERTICAL_EXIT_SCALE_REDUCTION_FACTOR;
1122     if (verticalExitNodeScale_ < VERTICAL_EXIT_SCALE_MIN_VALUE) {
1123         verticalExitNodeScale_ = VERTICAL_EXIT_SCALE_MIN_VALUE;
1124     }
1125     curNodeContext->UpdateTransformScale({verticalExitNodeScale_, verticalExitNodeScale_});
1126 
1127     // blur
1128     verticalExitNodeBlur_ = exitNodePercent * VERTICAL_EXIT_BLUR_REDUCTION_FACTOR;
1129 
1130     if (verticalExitNodeBlur_ > VERTICAL_EXIT_BLUR_MAX_VALUE) {
1131         verticalExitNodeBlur_ = VERTICAL_EXIT_BLUR_MAX_VALUE;
1132     }
1133     BlurOption blurOption;
1134     curNodeContext->UpdateBackBlur(Dimension(verticalExitNodeBlur_, DimensionUnit::PERCENT), blurOption);
1135 
1136     // alpha
1137     verticalExitNodeOpacity_ = 1.0f -  exitNodePercent  * VERTICAL_EXIT_ALPHA_REDUCTION_FACTOR;
1138     if (verticalExitNodeOpacity_ < 0.0f) {
1139         verticalExitNodeOpacity_ = 0.0f;
1140     }
1141     curNodeContext->UpdateOpacity(verticalExitNodeOpacity_);
1142 }
1143 
CalcBackgroundByPercent(const std::shared_ptr<Color> & colorA,const std::shared_ptr<Color> & colorB,float percent)1144 std::shared_ptr<Color> ArcSwiperPattern::CalcBackgroundByPercent(const std::shared_ptr<Color>& colorA,
1145     const std::shared_ptr<Color>& colorB, float percent)
1146 {
1147     Color retColor = Color::TRANSPARENT;
1148     Color tempColorA = Color::TRANSPARENT;
1149     Color tempColorB = Color::TRANSPARENT;
1150     if (colorA) {
1151         tempColorA = *colorA;
1152     }
1153     if (colorB) {
1154         tempColorB = *colorB;
1155     }
1156     auto r = tempColorA.GetRed() * (1.0f - percent) + tempColorB.GetRed() * percent;
1157     auto g = tempColorA.GetGreen() * (1.0f - percent) + tempColorB.GetGreen() * percent;
1158     auto b = tempColorA.GetBlue() * (1.0f - percent) + tempColorB.GetBlue() * percent;
1159     auto a = tempColorA.GetAlpha() * (1.0f - percent) + tempColorB.GetAlpha() * percent;
1160     retColor = retColor.FromARGB(a, r, g, b);
1161     std::shared_ptr<Color> colorPtr = std::make_shared<Color>(retColor);
1162     return colorPtr;
1163 }
1164 
PlayVerticalScrollEntryBackgroundAnimation(float percent,const RefPtr<FrameNode> & frameNode)1165 void ArcSwiperPattern::PlayVerticalScrollEntryBackgroundAnimation(float percent, const RefPtr<FrameNode>& frameNode)
1166 {
1167     entryNodeBackgroundColor_ = GetBackgroundColorValue(frameNode);
1168     auto parentNode = frameNode->GetParentFrameNode();
1169     CHECK_NULL_VOID(parentNode);
1170     auto parentContext = parentNode->GetRenderContext();
1171     CHECK_NULL_VOID(parentContext);
1172 
1173     std::shared_ptr<Color> beginColor = std::shared_ptr<Color>();
1174     std::shared_ptr<Color> endColor = std::shared_ptr<Color>();
1175     if (!preNodeBackgroundColor_ || (preNodeBackgroundColor_ && *preNodeBackgroundColor_ == Color::TRANSPARENT)) {
1176         beginColor = parentNodeBackgroundColor_;
1177     } else {
1178         beginColor = preNodeBackgroundColor_;
1179     }
1180 
1181     if (!entryNodeBackgroundColor_ || (entryNodeBackgroundColor_ && *entryNodeBackgroundColor_ == Color::TRANSPARENT)) {
1182         endColor = parentNodeBackgroundColor_;
1183     } else {
1184         endColor = entryNodeBackgroundColor_;
1185     }
1186 
1187     auto color = CalcBackgroundByPercent(beginColor, endColor, percent);
1188     PlayScrollBackgroundAnimation(color, parentNodeBackgroundColor_, parentContext, true);
1189 }
1190 
PlayVerticalScrollEntryAnimation(float swiperWidth,float startPos,const RefPtr<FrameNode> & frameNode)1191 void ArcSwiperPattern::PlayVerticalScrollEntryAnimation(float swiperWidth, float startPos,
1192     const RefPtr<FrameNode>& frameNode)
1193 {
1194     CHECK_NULL_VOID(frameNode);
1195     auto entryNodeContext = frameNode->GetRenderContext();
1196     CHECK_NULL_VOID(entryNodeContext);
1197     if (swiperWidth == 0) {
1198         return;
1199     }
1200     entryNodeContext->OnBackgroundColorUpdate(Color::TRANSPARENT);
1201     entryNodeContext->UpdateOpacity(0);
1202     auto entryNodePercent = (swiperWidth - std::abs(startPos)) / swiperWidth;
1203 
1204     // color
1205     PlayVerticalScrollEntryBackgroundAnimation(entryNodePercent, frameNode);
1206 
1207     if (entryNodePercent >= VERTICAL_ENTRY_OFFSET_PART) {
1208         // scale
1209         verticalEntryNodeScale_ = VERTICAL_ENTRY_SCALE_INITIAL_VALUE - VERTICAL_ENTRY_SCALE_REDUCTION_FACTOR *
1210             (entryNodePercent - VERTICAL_ENTRY_OFFSET_PART);
1211         if (verticalEntryNodeScale_ < 1.0f) {
1212             verticalEntryNodeScale_ = 1.0f;
1213         }
1214         entryNodeContext->UpdateTransformScale({verticalEntryNodeScale_, verticalEntryNodeScale_});
1215 
1216         // blur
1217         verticalEntryNodeBlur_ = VERTICAL_ENTRY_BLUR_INITIAL_VALUE - VERTICAL_ENTRY_BLUR_REDUCTION_FACTOR *
1218             (entryNodePercent - VERTICAL_ENTRY_OFFSET_PART);
1219 
1220         if (verticalEntryNodeBlur_ < 0) {
1221             verticalEntryNodeBlur_ = 0;
1222         }
1223         BlurOption blurOption;
1224         entryNodeContext->UpdateBackBlur(Dimension(verticalEntryNodeBlur_, DimensionUnit::PERCENT), blurOption);
1225 
1226         // alpha
1227         verticalEntryNodeOpacity_ = (entryNodePercent - VERTICAL_ENTRY_OFFSET_PART) * VERTICAL_ENTRY_BLUR_ALPHA_FACTOR;
1228         if (verticalEntryNodeOpacity_ > 1.0f) {
1229             verticalEntryNodeOpacity_ = 1.0f;
1230         }
1231         entryNodeContext->UpdateOpacity(verticalEntryNodeOpacity_);
1232     }
1233 }
1234 
PlayScrollAnimation(float currentDelta,float currentIndexOffset)1235 void ArcSwiperPattern::PlayScrollAnimation(float currentDelta, float currentIndexOffset)
1236 {
1237     if (!EnableTransitionAnimation()) {
1238         return;
1239     }
1240 
1241     if (!isDragging_) {
1242         canChangeDirectionFlag_ = false;
1243         return;
1244     }
1245 
1246     if (NearZero(currentDelta)) {
1247         return;
1248     }
1249 
1250     if (itemPosition_.size() <= 1) {
1251         return;
1252     }
1253 
1254     auto iter = itemPosition_.begin();
1255     if (currentIndexOffset > 0) {
1256         ++iter;
1257     }
1258     if (iter != itemPosition_.end()) {
1259         auto startPos = iter->second.startPos;
1260         if (NearEqual(startPos, currentIndexOffset)) {
1261             canChangeDirectionFlag_ = true;
1262         }
1263     }
1264 
1265     if (GetDirection() == Axis::HORIZONTAL) {
1266         HorizontalScrollAnimation(currentIndexOffset);
1267     } else {
1268         VerticalScrollAnimation(currentIndexOffset);
1269     }
1270 }
1271 
ResetBackgroundColor(const RefPtr<FrameNode> & frameNode)1272 void ArcSwiperPattern::ResetBackgroundColor(const RefPtr<FrameNode>& frameNode)
1273 {
1274     CHECK_NULL_VOID(frameNode);
1275     auto parentFrameNode = frameNode->GetParentFrameNode();
1276     CHECK_NULL_VOID(parentFrameNode);
1277     auto parentContext = parentFrameNode->GetRenderContext();
1278     CHECK_NULL_VOID(parentContext);
1279     auto parentColorPtr = GetBackgroundColorValue(parentFrameNode);
1280     if (axis_ == Axis::HORIZONTAL) {
1281         CHECK_NULL_VOID(parentColorPtr);
1282         auto backColor = GetBackgroundColorValue(frameNode);
1283         if (backColor) {
1284             frameNode->GetRenderContext()->OnBackgroundColorUpdate(*backColor);
1285         } else {
1286             frameNode->GetRenderContext()->OnBackgroundColorUpdate(Color::TRANSPARENT);
1287         }
1288         parentContext->OnBackgroundColorUpdate(*parentColorPtr);
1289     } else {
1290         parentNodeBackgroundColor_ = GetBackgroundColorValue(parentFrameNode);
1291         preNodeBackgroundColor_ = GetBackgroundColorValue(frameNode);
1292         if (preNodeBackgroundColor_ && *preNodeBackgroundColor_ != Color::TRANSPARENT) {
1293             parentContext->OnBackgroundColorUpdate(*preNodeBackgroundColor_);
1294         } else {
1295             CHECK_NULL_VOID(parentColorPtr);
1296             preNodeBackgroundColor_ = parentColorPtr;
1297             parentContext->OnBackgroundColorUpdate(*parentColorPtr);
1298         }
1299     }
1300 }
1301 
ResetAnimationParam()1302 void ArcSwiperPattern::ResetAnimationParam()
1303 {
1304     horizontalExitNodeScale_ = 1.0f;
1305     horizontalExitNodeBlur_ = 0.0f;
1306     horizontalExitNodeOpacity_ = 1.0f;
1307     horizontalEntryNodeScale_ = HORIZONTAL_ENTRY_SCALE_INITIAL_VALUE;
1308     horizontalEntryNodeBlur_ = HORIZONTAL_ENTRY_BLUR_VALUE;
1309     horizontalEntryNodeOpacity_ = 0.0f;
1310 
1311     verticalExitNodeScale_ = 1.0f;
1312     verticalExitNodeBlur_ = VERTICAL_EXIT_BLUR_INITIAL_VALUE;
1313     verticalExitNodeOpacity_ = 1.0f;
1314     verticalEntryNodeScale_ = VERTICAL_ENTRY_SCALE_VALUE;
1315     verticalEntryNodeOpacity_ = 0.0f;
1316     verticalEntryNodeBlur_ = 0.0f;
1317     for (auto item : itemPosition_) {
1318         auto node = item.second.node;
1319         CHECK_NULL_CONTINUE(node);
1320         auto context = node->GetRenderContext();
1321         CHECK_NULL_CONTINUE(context);
1322         context->UpdateOpacity(1);
1323         context->UpdateTransformScale({1.0f, 1.0f});
1324         BlurOption blurOption;
1325         context->UpdateBackBlur(Dimension(0.0f, DimensionUnit::PERCENT), blurOption);
1326         auto axis = GetDirection();
1327         if (axis_ == axis && axis == Axis::HORIZONTAL) {
1328             continue;
1329         }
1330         axis_ = axis;
1331         ResetBackgroundColor(node);
1332     }
1333 }
1334 
ResetFrameNodeAnimation(const RefPtr<FrameNode> & frameNode,bool resetBackgroundcolor)1335 void ArcSwiperPattern::ResetFrameNodeAnimation(const RefPtr<FrameNode>& frameNode, bool resetBackgroundcolor)
1336 {
1337     CHECK_NULL_VOID(frameNode);
1338     auto context = frameNode->GetRenderContext();
1339     CHECK_NULL_VOID(context);
1340     context->UpdateTransformScale({1.0f, 1.0f});
1341     context->UpdateOpacity(1.0f);
1342     BlurOption blurOption;
1343     context->UpdateBackBlur(Dimension(0.0f, DimensionUnit::PERCENT), blurOption);
1344     if (resetBackgroundcolor) {
1345         auto backColor = GetBackgroundColorValue(frameNode);
1346         if (backColor) {
1347             context->OnBackgroundColorUpdate(*backColor);
1348         }
1349     }
1350 }
1351 
ResetCurrentFrameNodeAnimation()1352 void ArcSwiperPattern::ResetCurrentFrameNodeAnimation()
1353 {
1354     auto curInter = itemPosition_.find(currentIndex_);
1355     if (curInter != itemPosition_.end()) {
1356         auto curFrameNode = curInter->second.node;
1357         CHECK_NULL_VOID(curFrameNode);
1358         ResetFrameNodeAnimation(curFrameNode, true);
1359     }
1360 }
1361 
ResetParentNodeColor()1362 void ArcSwiperPattern::ResetParentNodeColor()
1363 {
1364     auto curInter = itemPosition_.find(currentIndex_);
1365     if (curInter == itemPosition_.end()) {
1366         return;
1367     }
1368     auto curFrameNode = curInter->second.node;
1369     CHECK_NULL_VOID(curFrameNode);
1370     auto parentNode = curFrameNode->GetParentFrameNode();
1371     CHECK_NULL_VOID(parentNode);
1372     auto parentContext = parentNode->GetRenderContext();
1373     CHECK_NULL_VOID(parentContext);
1374     auto colorPtr = GetBackgroundColorValue(parentNode);
1375     if (colorPtr) {
1376         parentContext->OnBackgroundColorUpdate(*colorPtr);
1377     } else {
1378         parentContext->OnBackgroundColorUpdate(Color::TRANSPARENT);
1379     }
1380 }
1381 
EnableTransitionAnimation() const1382 bool ArcSwiperPattern::EnableTransitionAnimation() const
1383 {
1384     if (SupportSwiperCustomAnimation() || IsDisableTransitionAnimation()) {
1385         return false;
1386     }
1387     return true;
1388 }
1389 
GetCurve() const1390 RefPtr<Curve> ArcSwiperPattern::GetCurve() const
1391 {
1392     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
1393     CHECK_NULL_RETURN(swiperPaintProperty, nullptr);
1394     if (EnableTransitionAnimation()) {
1395         return Curves::FRICTION;
1396     }
1397     return swiperPaintProperty->GetCurve().value_or(nullptr);
1398 }
1399 
GetDuration() const1400 int32_t ArcSwiperPattern::GetDuration() const
1401 {
1402     auto swiperPaintProperty = GetPaintProperty<SwiperPaintProperty>();
1403     int32_t defaultDuration = 0;
1404     if (EnableTransitionAnimation()) {
1405         if (GetDirection() == Axis::HORIZONTAL) {
1406             defaultDuration = HORIZONTAL_ANIMAION_DEFAULT_DURATION;
1407         } else {
1408             defaultDuration = VERTICAL_ANIMAION_DEFAULT_DURATION;
1409         }
1410     } else {
1411         defaultDuration = NO_ANIMAION_DEFAULT_DURATION;
1412     }
1413     CHECK_NULL_RETURN(swiperPaintProperty, defaultDuration);
1414     return swiperPaintProperty->GetDuration().value_or(defaultDuration);
1415 }
1416 
CalcTime(int32_t time)1417 int32_t ArcSwiperPattern::CalcTime(int32_t time)
1418 {
1419     auto duration = GetDuration();
1420     int32_t baseTime = 0;
1421     if (GetDirection() == Axis::HORIZONTAL) {
1422         baseTime = HORIZONTAL_ANIMAION_DEFAULT_DURATION;
1423     } else {
1424         baseTime = VERTICAL_ANIMAION_DEFAULT_DURATION;
1425     }
1426     return time * duration / baseTime;
1427 }
1428 
GetAndResetDisableFlushFocus()1429 bool ArcSwiperPattern::GetAndResetDisableFlushFocus()
1430 {
1431     bool ret = isDisableFlushFocus_;
1432     isDisableFlushFocus_ = false;
1433     return ret;
1434 }
1435 
1436 #ifdef SUPPORT_DIGITAL_CROWN
SetDigitalCrownSensitivity(CrownSensitivity sensitivity)1437 void ArcSwiperPattern::SetDigitalCrownSensitivity(CrownSensitivity sensitivity)
1438 {
1439     crownSensitivity_ = sensitivity;
1440 }
1441 
InitOnCrownEventInternal(const RefPtr<FocusHub> & focusHub)1442 void ArcSwiperPattern::InitOnCrownEventInternal(const RefPtr<FocusHub>& focusHub)
1443 {
1444     auto host = GetHost();
1445     auto onCrownEvent = [weak = WeakClaim(this), weakNode = AceType::WeakClaim(AceType::RawPtr(
1446         host))](const CrownEvent& event) -> bool {
1447         auto pattern = weak.Upgrade();
1448         CHECK_NULL_RETURN(pattern, false);
1449         auto node = weakNode.Upgrade();
1450         CHECK_NULL_RETURN(node, false);
1451 
1452         auto offset = node->GetGeometryNode()->GetFrameOffset();
1453         auto contentSize = node->GetGeometryNode()->GetFrameSize();
1454         auto swiperPattern = node->GetPattern<SwiperPattern>();
1455         float centerX = contentSize.Width() * 0.5 + offset.GetX();
1456         float centerY = contentSize.Height() * 0.5 + offset.GetY();
1457         OffsetF center;
1458         center.SetX(centerX);
1459         center.SetY(centerY);
1460         pattern->HandleCrownEvent(event, center, offset);
1461         return true;
1462     };
1463     focusHub->SetOnCrownEventInternal(std::move(onCrownEvent));
1464 }
1465 
IsCrownSpring() const1466 bool ArcSwiperPattern::IsCrownSpring() const
1467 {
1468     return isCrownSpring_;
1469 }
1470 
SetIsCrownSpring(bool isCrownSpring)1471 void ArcSwiperPattern::SetIsCrownSpring(bool isCrownSpring)
1472 {
1473     isCrownSpring_ = false;
1474 }
1475 
HandleCrownEvent(const CrownEvent & event,const OffsetF & center,const OffsetF & offset)1476 void ArcSwiperPattern::HandleCrownEvent(const CrownEvent& event, const OffsetF& center, const OffsetF& offset)
1477 {
1478     DimensionOffset centerDimension(center);
1479     Offset globalLocation(centerDimension.GetX().ConvertToPx(), centerDimension.GetY().ConvertToPx());
1480     GestureEvent info;
1481     info.SetSourceDevice(SourceType::CROWN);
1482     info.SetSourceTool(SourceTool::UNKNOWN);
1483     info.SetGlobalLocation(globalLocation);
1484     double mainDelta = GetCrownRotatePx(event);
1485     switch (event.action) {
1486         case CrownAction::BEGIN:
1487             HandleCrownActionBegin(event.degree, mainDelta, info, offset);
1488             break;
1489         case CrownAction::UPDATE:
1490             HandleCrownActionUpdate(event.degree, mainDelta, info, offset);
1491             break;
1492         case CrownAction::END:
1493             HandleCrownActionEnd(event.degree, mainDelta, info, offset);
1494             break;
1495         default:
1496             HandleCrownActionCancel();
1497             break;
1498     }
1499 }
1500 
HandleCrownActionBegin(double degree,double mainDelta,GestureEvent & info,const OffsetF & offset)1501 void ArcSwiperPattern::HandleCrownActionBegin(double degree, double mainDelta,
1502     GestureEvent& info, const OffsetF& offset)
1503 {
1504     if (IsPropertyAnimationRunning() || IsTranslateAnimationRunning()) {
1505         UpdateCrownVelocity(degree, mainDelta);
1506         auto host = GetHost();
1507         CHECK_NULL_VOID(host);
1508         auto pipelineContext = host->GetContext();
1509         CHECK_NULL_VOID(pipelineContext);
1510         auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1511         CHECK_NULL_VOID(theme);
1512         if (std::abs(degree) < theme->GetSpringVelocityThreshold()) {
1513             auto length = (direction_ == Axis::HORIZONTAL ? info.GetGlobalLocation().GetX() - offset.GetX():
1514                         info.GetGlobalLocation().GetY() - offset.GetY()) * 2;
1515             double offsetLen = direction_ == Axis::VERTICAL ? accumulativeCrownPx_.GetY() : accumulativeCrownPx_.GetX();
1516             if (std::abs(offsetLen) < length * theme->GetCrownTranslocationRatio()) {
1517                 return;
1518             }
1519         }
1520         isDisableFlushFocus_ = true;
1521     }
1522     accumulativeCrownPx_.Reset();
1523     UpdateCrownVelocity(degree, mainDelta);
1524     info.SetMainDelta(mainDelta);
1525     info.SetMainVelocity(crownVelocity_);
1526     InitIndexCanChangeMap();
1527     FireAndCleanScrollingListener();
1528     HandleDragStart(info);
1529     NotifyParentScrollStart(WeakClaim(this), direction_ == Axis::HORIZONTAL ? info.GetGlobalLocation().GetX()
1530                                     : info.GetGlobalLocation().GetY());
1531     TouchLocationInfo touchLocationInfo(1);
1532     touchLocationInfo.SetGlobalLocation(info.GetGlobalLocation());
1533     HandleTouchDown(touchLocationInfo);
1534     isCrownSpring_ = false;
1535     isHandleCrownActionEnd_ = false;
1536 }
1537 
HandleCrownActionUpdate(double degree,double mainDelta,GestureEvent & info,const OffsetF & offset)1538 void ArcSwiperPattern::HandleCrownActionUpdate(double degree, double mainDelta,
1539     GestureEvent& info, const OffsetF& offset)
1540 {
1541     if (isCrownSpring_) {
1542         return;
1543     }
1544     if (isChanged_ && oldCurrentIndex_ == currentIndex_ &&
1545         !(degree > 0 && currentIndex_ == 0) &&
1546         !(degree < 0 && currentIndex_ + 1 == TotalCount())) {
1547         return;
1548     }
1549     isChanged_ = false;
1550     if (!isDragging_) {
1551         HandleCrownActionBegin(degree, mainDelta, info, offset);
1552         return;
1553     }
1554 
1555     oldCurrentIndex_ = currentIndex_;
1556     UpdateCrownVelocity(degree, mainDelta);
1557     info.SetMainDelta(mainDelta);
1558     info.SetMainVelocity(crownVelocity_);
1559     HandleDragUpdate(info);
1560     auto pipelineContext = PipelineBase::GetCurrentContext();
1561     CHECK_NULL_VOID(pipelineContext);
1562     auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1563     CHECK_NULL_VOID(theme);
1564     if (std::abs(degree) < theme->GetSpringVelocityThreshold()) {
1565         auto length = (direction_ == Axis::HORIZONTAL ? info.GetGlobalLocation().GetX() - offset.GetX():
1566                     info.GetGlobalLocation().GetY() - offset.GetY()) * 2;
1567         double offsetLen = direction_ == Axis::VERTICAL ? accumulativeCrownPx_.GetY() : accumulativeCrownPx_.GetX();
1568         if (std::abs(offsetLen) >= length * theme->GetCrownTranslocationRatio()) {
1569             isCrownSpring_ = true;
1570             HandleDragEnd(crownTurnVelocity_);
1571             StartVibrator(degree > 0);
1572             HandleTouchUp();
1573             isChanged_ = true;
1574             accumulativeCrownPx_.Reset();
1575         }
1576     } else {
1577         isCrownSpring_ = true;
1578         HandleDragEnd(crownVelocity_);
1579         StartVibrator(degree > 0);
1580         HandleTouchUp();
1581         isChanged_ = true;
1582         accumulativeCrownPx_.Reset();
1583     }
1584 }
1585 
HandleCrownActionEnd(double degree,double mainDelta,GestureEvent & info,const OffsetF & offset)1586 void ArcSwiperPattern::HandleCrownActionEnd(
1587     double degree, double mainDelta, GestureEvent& info, const OffsetF& offset)
1588 {
1589     isChanged_ = false;
1590     if (!isDragging_ || isHandleCrownActionEnd_) {
1591         return;
1592     }
1593     isHandleCrownActionEnd_ = true;
1594     UpdateCrownVelocity(degree, mainDelta, true);
1595     info.SetMainDelta(mainDelta);
1596     info.SetMainVelocity(crownVelocity_);
1597     auto pipelineContext = PipelineBase::GetCurrentContext();
1598     CHECK_NULL_VOID(pipelineContext);
1599     auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1600     CHECK_NULL_VOID(theme);
1601     isCrownSpring_ = true;
1602     if (std::abs(degree) < theme->GetSpringVelocityThreshold()) {
1603         auto length = (direction_ == Axis::HORIZONTAL ? info.GetGlobalLocation().GetX() - offset.GetX():
1604                     info.GetGlobalLocation().GetY() - offset.GetY()) * 2;
1605         double offsetLen = direction_ == Axis::VERTICAL ? accumulativeCrownPx_.GetY() : accumulativeCrownPx_.GetX();
1606         if (std::abs(offsetLen) >= length * theme->GetCrownTranslocationRatio()) {
1607             HandleDragEnd(crownTurnVelocity_);
1608             StartVibrator(degree > 0);
1609             HandleTouchUp();
1610         } else {
1611             HandleDragEnd(0.0);
1612             HandleTouchUp();
1613         }
1614     } else {
1615         HandleDragEnd(crownVelocity_);
1616         StartVibrator(degree > 0);
1617         HandleTouchUp();
1618     }
1619     accumulativeCrownPx_.Reset();
1620 }
1621 
StartVibrator(bool isLeft)1622 void ArcSwiperPattern::StartVibrator(bool isLeft)
1623 {
1624     if ((isLeft && currentIndex_ == 0) || (!isLeft && currentIndex_ == TotalCount() - 1)) {
1625         return;
1626     }
1627     VibratorUtils::StartVibraFeedback(HAPTIC_STRENGTH3);
1628 }
1629 
HandleCrownActionCancel()1630 void ArcSwiperPattern::HandleCrownActionCancel()
1631 {
1632     isChanged_ = false;
1633     isCrownSpring_ = false;
1634     isHandleCrownActionEnd_ = false;
1635     if (!isDragging_) {
1636         return;
1637     }
1638 
1639     HandleDragEnd(0.0);
1640     HandleTouchUp();
1641     isDragging_ = false;
1642     accumulativeCrownPx_.Reset();
1643 }
1644 
GetCrownRotatePx(const CrownEvent & event) const1645 double ArcSwiperPattern::GetCrownRotatePx(const CrownEvent& event) const
1646 {
1647     double velocity = event.degree;
1648     double px = 0.0;
1649     auto pipelineContext = PipelineBase::GetCurrentContext();
1650     CHECK_NULL_RETURN(pipelineContext, 0.0);
1651     auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1652     CHECK_NULL_RETURN(theme, 0.0);
1653 
1654     if (LessOrEqualCustomPrecision(velocity, theme->GetSlowVelocityThreshold(), 0.01f)) {
1655         px = theme->GetDisplayControlRatioVerySlow() * velocity;
1656     } else if (LessOrEqualCustomPrecision(velocity, theme->GetMediumVelocityThreshold(), 0.01f)) {
1657         px = theme->GetDisplayControlRatioSlow() * velocity;
1658     } else if (LessOrEqualCustomPrecision(velocity, theme->GetFastVelocityThreshold(), 0.01f)) {
1659         px = theme->GetDisplayControlRatioMedium() * velocity;
1660     } else {
1661         px = theme->GetDisplayControlRatioFast() * velocity;
1662     }
1663 
1664     switch (crownSensitivity_) {
1665         case CrownSensitivity::LOW:
1666             px *= theme->GetCrownSensitivityLow();
1667             break;
1668         case CrownSensitivity::MEDIUM:
1669             px *= theme->GetCrownSensitivityMedium();
1670             break;
1671         case CrownSensitivity::HIGH:
1672             px *= theme->GetCrownSensitivityHigh();
1673             break;
1674         default:
1675             break;
1676     }
1677     return px;
1678 }
1679 
UpdateCrownVelocity(double degree,double mainDelta,bool isEnd)1680 void ArcSwiperPattern::UpdateCrownVelocity(double degree, double mainDelta, bool isEnd)
1681 {
1682     if (isEnd) {
1683         return;
1684     }
1685     if (direction_ == Axis::VERTICAL) {
1686         accumulativeCrownPx_ += Offset(0, mainDelta);
1687     } else {
1688         accumulativeCrownPx_ += Offset(mainDelta, 0);
1689     }
1690     auto turnVelocity = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)
1691                                                         ? NEW_MIN_TURN_PAGE_VELOCITY
1692                                                         : MIN_TURN_PAGE_VELOCITY;
1693     auto pipelineContext = PipelineBase::GetCurrentContext();
1694     CHECK_NULL_VOID(pipelineContext);
1695     auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
1696     CHECK_NULL_VOID(theme);
1697     crownVelocity_ = degree * turnVelocity / theme->GetSpringVelocityThreshold();
1698     if (degree > 0) {
1699         crownTurnVelocity_ = turnVelocity + 1;
1700     } else {
1701         crownTurnVelocity_ = -turnVelocity - 1;
1702     }
1703 }
1704 #endif
1705 } // namespace OHOS::Ace::NG