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