• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_indicator/dot_indicator/dot_indicator_modifier.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/animation/spring_curve.h"
20 #include "core/components_ng/render/animation_utils.h"
21 #include "core/components_ng/render/drawing.h"
22 #include "core/components_ng/render/paint_property.h"
23 
24 namespace OHOS::Ace::NG {
25 namespace {
26 constexpr int32_t POINT_HOVER_ANIMATION_DURATION = 100;
27 constexpr int32_t COMPONENT_DILATE_ANIMATION_DURATION = 250;
28 constexpr int32_t COMPONENT_SHRINK_ANIMATION_DURATION = 300;
29 constexpr int32_t MOUSE_PRESS_ANIMATION_DURATION = 250;
30 
31 constexpr float BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY = 0.4f;
32 constexpr float CENTER_BEZIER_CURVE_MASS = 0.0f;
33 constexpr float CENTER_BEZIER_CURVE_STIFFNESS = 1.0f;
34 constexpr float CENTER_BEZIER_CURVE_DAMPING = 1.0f;
35 constexpr uint32_t ITEM_HALF_WIDTH = 0;
36 constexpr uint32_t ITEM_HALF_HEIGHT = 1;
37 constexpr uint32_t SELECTED_ITEM_HALF_WIDTH = 2;
38 constexpr uint32_t SELECTED_ITEM_HALF_HEIGHT = 3;
39 constexpr float TOUCH_BOTTOM_CURVE_VELOCITY = 0.1f;
40 constexpr float TOUCH_BOTTOM_CURVE_MASS = 0.2f;
41 constexpr float TOUCH_BOTTOM_CURVE_STIFFNESS = 0.48f;
42 constexpr float TOUCH_BOTTOM_CURVE_DAMPING = 1.0f;
43 constexpr float TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE = 1.225f;
44 constexpr float TOUCH_BOTTOM_BACKGROUND_HEIGHT_MULTIPLE = 0.8f;
45 constexpr float TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE = 0.0125f;
46 constexpr int32_t DEFAULT_TOUCH_BOTTOM_ANIMATION_DURATION = 200;
47 constexpr int32_t DEFAULT_OPACITY_ANIMATION_DURATION = 100;
48 constexpr float LOOP_TRANSLATE_DURATION_PERCENT = 0.5f;
49 constexpr float LOOP_OPACITY_DURATION_PERCENT = 0.25f;
50 constexpr uint8_t TARGET_ALPHA = 255;
51 constexpr int32_t BLACK_POINT_DURATION = 400;
52 constexpr float DEFAULT_MINIMUM_AMPLITUDE_PX = 1.0f;
53 constexpr float HALF_FLOAT = 0.5f;
54 constexpr float TWO_FLOAT = 2.0f;
55 constexpr int32_t LONG_POINT_STEP_TWO = 2;
56 constexpr int32_t LONG_POINT_STEP_THREE = 3;
57 constexpr int32_t LONG_POINT_STEP_FOUR = 4;
58 // velocity:0, mass:1, stiffness:81, damping:11
59 const auto LONG_POINT_DEFAULT_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0, 1, 81, 11);
60 const auto LONG_POINT_STEP_TWO_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0, 1, 108, 16);
61 const auto LONG_POINT_STEP_THREE_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0, 1, 128, 18);
62 const auto LONG_POINT_STEP_FOUR_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0, 1, 128, 20);
63 const auto LONG_POINT_STEP_FIVE_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0, 1, 148, 28);
64 } // namespace
65 
onDraw(DrawingContext & context)66 void DotIndicatorModifier::onDraw(DrawingContext& context)
67 {
68     ContentProperty contentProperty;
69     contentProperty.backgroundColor = backgroundColor_->Get().ToColor();
70     contentProperty.vectorBlackPointCenterX = vectorBlackPointCenterX_->Get();
71     contentProperty.longPointLeftCenterX = longPointLeftCenterX_->Get();
72     contentProperty.longPointRightCenterX = longPointRightCenterX_->Get();
73     contentProperty.normalToHoverPointDilateRatio = normalToHoverPointDilateRatio_->Get();
74     contentProperty.hoverToNormalPointDilateRatio = hoverToNormalPointDilateRatio_->Get();
75     contentProperty.longPointDilateRatio = longPointDilateRatio_->Get();
76     contentProperty.indicatorPadding = indicatorPadding_->Get();
77     contentProperty.indicatorMargin = indicatorMargin_->Get();
78     contentProperty.itemHalfSizes = itemHalfSizes_->Get();
79     SetFocusedAndSelectedColor(contentProperty);
80     PaintBackground(context, contentProperty);
81     PaintContent(context, contentProperty);
82 }
83 
SetFocusedAndSelectedColor(ContentProperty & contentProperty)84 void DotIndicatorModifier::SetFocusedAndSelectedColor(ContentProperty& contentProperty)
85 {
86     auto indicatorTheme = GetSwiperIndicatorTheme();
87     CHECK_NULL_VOID(indicatorTheme);
88     paddingSide_ = indicatorTheme->GetIndicatorPaddingDot();
89     scaleIndicator_ = indicatorTheme->GetIndicatorScale();
90     Color currentSelectedColor = selectedColor_->Get().ToColor();
91     Color currentUnselectedColor = unselectedColor_->Get();
92     if (isFocused_->Get()) {
93         originalUnselectColor_ = (indicatorTheme->GetColor() == currentUnselectedColor)
94                                      ? indicatorTheme->GetFocusUnSelectedColor()
95                                      : currentUnselectedColor;
96         originalSelectColor_ = (indicatorTheme->GetSelectedColor() == currentSelectedColor)
97                                    ? indicatorTheme->GetFocusedSelectedColor()
98                                    : currentSelectedColor;
99         contentProperty.backgroundColor = indicatorTheme->GetFocusedBgColor();
100     } else {
101         originalUnselectColor_ = currentUnselectedColor;
102         originalSelectColor_ = currentSelectedColor;
103         contentProperty.backgroundColor = backgroundColor_->Get().ToColor();
104     }
105 }
106 
PaintBackground(DrawingContext & context,ContentProperty & contentProperty)107 void DotIndicatorModifier::PaintBackground(DrawingContext& context, ContentProperty& contentProperty)
108 {
109     CHECK_NULL_VOID(contentProperty.backgroundColor.GetAlpha());
110     auto itemWidth = contentProperty.itemHalfSizes[ITEM_HALF_WIDTH] * 2;
111     auto itemHeight = contentProperty.itemHalfSizes[ITEM_HALF_HEIGHT] * 2;
112     auto selectedItemWidth = contentProperty.itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * 2;
113     auto selectedItemHeight = contentProperty.itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT] * 2;
114     auto pointNumber = static_cast<float>(contentProperty.vectorBlackPointCenterX.size());
115     float allPointDiameterSum = itemWidth * static_cast<float>(pointNumber + 1);
116     if (isCustomSize_) {
117         allPointDiameterSum = itemWidth * static_cast<float>(pointNumber - 1) + selectedItemWidth;
118     }
119     float allPointSpaceSum = static_cast<float>(GetIndicatorDotItemSpace().ConvertToPx()) * (pointNumber - 1);
120 
121     // Background necessary property
122     float rectWidth =
123         contentProperty.indicatorPadding + allPointDiameterSum + allPointSpaceSum + contentProperty.indicatorPadding;
124     auto indicatorTheme = GetSwiperIndicatorTheme();
125     CHECK_NULL_VOID(indicatorTheme);
126     auto indicatorHeightPadding = indicatorTheme->GetIndicatorBgHeight().ConvertToPx();
127     float rectHeight = indicatorHeightPadding + itemHeight + indicatorHeightPadding;
128     if (selectedItemHeight > itemHeight) {
129         rectHeight = indicatorHeightPadding + selectedItemHeight + indicatorHeightPadding;
130     }
131 
132     auto [rectLeft, rectRight, rectTop, rectBottom] =
133         CalcAndAdjustIndicatorPaintRect(contentProperty, rectWidth, rectHeight);
134     if (Positive(pointNumber)) {
135         auto [leftCenterX, rightCenterX] = GetTouchBottomCenterX(contentProperty);
136         leftCenterX = std::min(leftCenterX, contentProperty.vectorBlackPointCenterX[0]);
137         rightCenterX = std::max(rightCenterX,
138             contentProperty.vectorBlackPointCenterX[static_cast<int32_t>(pointNumber) - 1]);
139         auto rectPadding = contentProperty.indicatorPadding + itemWidth / 2;
140         if (axis_ == Axis::VERTICAL) {
141             rectTop = std::min(rectTop, leftCenterX - rectPadding);
142             rectBottom = std::max(rectBottom, rightCenterX + rectPadding);
143         } else {
144             rectLeft = std::min(rectLeft, leftCenterX - rectPadding);
145             rectRight = std::max(rectRight, rightCenterX + rectPadding);
146         }
147     }
148     // Paint background
149     RSCanvas& canvas = context.canvas;
150     RSBrush brush;
151     brush.SetAntiAlias(true);
152     brush.SetColor(ToRSColor(contentProperty.backgroundColor));
153     canvas.AttachBrush(brush);
154     auto radius = axis_ == Axis::HORIZONTAL ? rectHeight : rectWidth;
155     canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, radius, radius });
156     canvas.DetachBrush();
157 }
158 
CalcAndAdjustIndicatorPaintRect(const ContentProperty & contentProperty,float & rectWidth,float & rectHeight)159 std::tuple<float, float, float, float> DotIndicatorModifier::CalcAndAdjustIndicatorPaintRect(
160     const ContentProperty& contentProperty, float& rectWidth, float& rectHeight)
161 {
162     auto widthChangeValue = (backgroundWidthDilateRatio_->Get() - 1.0f) * rectWidth;
163     auto heightChangeValue = (1.0f - backgroundHeightDilateRatio_->Get()) * rectHeight;
164     if (axis_ == Axis::VERTICAL) {
165         std::swap(widthChangeValue, heightChangeValue);
166     }
167     // Property to get the rectangle offset
168     float rectLeft =
169         axis_ == Axis::HORIZONTAL ? contentProperty.indicatorMargin.GetX() : contentProperty.indicatorMargin.GetY();
170     float rectTop =
171         axis_ == Axis::HORIZONTAL ? contentProperty.indicatorMargin.GetY() : contentProperty.indicatorMargin.GetX();
172     // Adapter circle and rect
173     float rectRight = rectLeft + (axis_ == Axis::HORIZONTAL ? rectWidth : rectHeight);
174     float rectBottom = rectTop + (axis_ == Axis::HORIZONTAL ? rectHeight : rectWidth);
175 
176     if (axis_ == Axis::HORIZONTAL) {
177         boundsRectF_.SetWidth(rectRight - rectLeft + widthChangeValue * TWO_FLOAT);
178         boundsRectF_.SetHeight(rectBottom - rectTop);
179         if (touchBottomType_ == TouchBottomType::START) {
180             rectLeft -= widthChangeValue;
181         }
182         if (touchBottomType_ == TouchBottomType::END) {
183             rectRight += widthChangeValue;
184         }
185         rectTop = rectTop + heightChangeValue * 0.5f;
186         rectBottom = rectBottom - heightChangeValue * 0.5f;
187         rectHeight -= heightChangeValue;
188     } else {
189         boundsRectF_.SetWidth(rectRight - rectLeft);
190         boundsRectF_.SetHeight(rectBottom - rectTop + heightChangeValue * TWO_FLOAT);
191         if (touchBottomType_ == TouchBottomType::START) {
192             rectTop -= heightChangeValue;
193         }
194         if (touchBottomType_ == TouchBottomType::END) {
195             rectBottom += heightChangeValue;
196         }
197         rectLeft = rectLeft + widthChangeValue * 0.5f;
198         rectRight = rectRight - widthChangeValue * 0.5f;
199         rectWidth -= widthChangeValue;
200     }
201     boundsRectF_.SetLeft(rectLeft);
202     boundsRectF_.SetTop(rectTop);
203     return { rectLeft, rectRight, rectTop, rectBottom };
204 }
205 
GetTouchBottomCenterX(ContentProperty & contentProperty)206 std::pair<float, float> DotIndicatorModifier::GetTouchBottomCenterX(ContentProperty& contentProperty)
207 {
208     float leftCenterX = contentProperty.longPointLeftCenterX;
209     float rightCenterX = contentProperty.longPointRightCenterX;
210 
211     if (contentProperty.vectorBlackPointCenterX.empty()) {
212         return { leftCenterX, rightCenterX };
213     }
214     auto totalCount = contentProperty.vectorBlackPointCenterX.size();
215     // 2.0 means get the long point radius
216     float radius = (rightCenterX - leftCenterX) / 2.0f;
217     bool isLeftTouchBottom = (currentIndex_ == static_cast<int32_t>(totalCount) - 1);
218     bool isRightTouchBottom = (currentIndex_ == 0);
219 
220     if ((animationState_ == TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT && isLeftTouchBottom) ||
221         (animationState_ == TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT && isRightTouchBottom)) {
222         leftCenterX = contentProperty.vectorBlackPointCenterX[0] - radius;
223         rightCenterX = contentProperty.vectorBlackPointCenterX[0] + radius;
224     } else if ((animationState_ == TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT && isLeftTouchBottom) ||
225         (animationState_ == TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT && isRightTouchBottom)) {
226         leftCenterX = contentProperty.vectorBlackPointCenterX[totalCount - 1] - radius;
227         rightCenterX = contentProperty.vectorBlackPointCenterX[totalCount - 1] + radius;
228     }
229 
230     return { leftCenterX, rightCenterX };
231 }
232 
PaintContent(DrawingContext & context,ContentProperty & contentProperty)233 void DotIndicatorModifier::PaintContent(DrawingContext& context, ContentProperty& contentProperty)
234 {
235     RSCanvas& canvas = context.canvas;
236     OffsetF selectedCenter = {};
237     auto totalCount = contentProperty.vectorBlackPointCenterX.size();
238     if (totalCount == 0 && NearZero(contentProperty.longPointLeftCenterX) &&
239         NearZero(contentProperty.longPointRightCenterX)) {
240         return;
241     }
242 
243     for (size_t i = 0; i < totalCount; ++i) {
244         LinearVector<float> itemHalfSizes = GetItemHalfSizes(i, contentProperty);
245         OffsetF center = { contentProperty.vectorBlackPointCenterX[i], centerY_ };
246         if (static_cast<int32_t>(i) != currentIndex_) {
247             PaintUnselectedIndicator(canvas, center, itemHalfSizes, false, LinearColor(originalUnselectColor_));
248         } else {
249             selectedCenter = center;
250             PaintUnselectedIndicator(canvas, center, itemHalfSizes, isCustomSize_,
251                 LinearColor(originalUnselectColor_));
252         }
253     }
254 
255     auto [leftCenterX, rightCenterX] = GetTouchBottomCenterX(contentProperty);
256 
257     OffsetF leftCenter = { leftCenterX, centerY_ };
258     OffsetF rightCenter = { rightCenterX, centerY_ };
259     OffsetF centerDistance = rightCenter - leftCenter;
260     OffsetF centerDilateDistance = centerDistance * contentProperty.longPointDilateRatio;
261     leftCenter -= (centerDilateDistance - centerDistance) * 0.5;
262     rightCenter += (centerDilateDistance - centerDistance) * 0.5;
263     PaintSelectedIndicator(canvas, leftCenter, rightCenter,
264         contentProperty.itemHalfSizes * contentProperty.longPointDilateRatio);
265 
266     bool isLeftTouchBottom = (currentIndex_ == static_cast<int32_t>(totalCount) - 1);
267     bool isRightTouchBottom = (currentIndex_ == 0);
268     bool isTouchBottom = (isLeftTouchBottom || isRightTouchBottom);
269     if (!isTouchBottom || totalCount == 0 || !isTouchBottomLoop_) {
270         return;
271     }
272 
273     size_t index = 0;
274     if (isRightTouchBottom) {
275         index = totalCount - 1;
276     }
277     LinearVector<float> itemHalfSizes = GetItemHalfSizes(index, contentProperty);
278     OffsetF center = { contentProperty.vectorBlackPointCenterX[index], centerY_ };
279     PaintUnselectedIndicator(canvas, center, itemHalfSizes, false, touchBottomPointColor_->Get());
280 }
281 
GetItemHalfSizes(size_t index,ContentProperty & contentProperty)282 LinearVector<float> DotIndicatorModifier::GetItemHalfSizes(size_t index, ContentProperty& contentProperty)
283 {
284     if (normalToHoverIndex_.has_value() && normalToHoverIndex_ == index) {
285         return contentProperty.itemHalfSizes * contentProperty.normalToHoverPointDilateRatio;
286     }
287     if (hoverToNormalIndex_.has_value() && hoverToNormalIndex_ == index) {
288         return contentProperty.itemHalfSizes * contentProperty.hoverToNormalPointDilateRatio;
289     }
290     return contentProperty.itemHalfSizes;
291 }
292 
PaintUnselectedIndicator(RSCanvas & canvas,const OffsetF & center,const LinearVector<float> & itemHalfSizes,bool currentIndexFlag,const LinearColor & indicatorColor)293 void DotIndicatorModifier::PaintUnselectedIndicator(RSCanvas& canvas, const OffsetF& center,
294     const LinearVector<float>& itemHalfSizes, bool currentIndexFlag, const LinearColor& indicatorColor)
295 {
296     RSBrush brush;
297     brush.SetAntiAlias(true);
298     brush.SetColor(ToRSColor(indicatorColor));
299     canvas.AttachBrush(brush);
300     if (!NearEqual(itemHalfSizes[ITEM_HALF_WIDTH], itemHalfSizes[ITEM_HALF_HEIGHT]) || currentIndexFlag ||
301         !isCustomSize_) {
302         float rectItemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * 2;
303         float rectItemHeight = itemHalfSizes[ITEM_HALF_HEIGHT] * 2;
304         float rectLeft =
305             (axis_ == Axis::HORIZONTAL ? center.GetX() - rectItemWidth * 0.5 : center.GetY() - rectItemHeight * 0.5);
306         float rectTop =
307             (axis_ == Axis::HORIZONTAL ? center.GetY() - rectItemHeight * 0.5 : center.GetX() - rectItemWidth * 0.5);
308         float rectRight =
309             (axis_ == Axis::HORIZONTAL ? center.GetX() + rectItemWidth * 0.5 : center.GetY() + rectItemHeight * 0.5);
310         float rectBottom =
311             (axis_ == Axis::HORIZONTAL ? center.GetY() + rectItemHeight * 0.5 : center.GetX() + rectItemWidth * 0.5);
312 
313         if (rectItemHeight > rectItemWidth || !isCustomSize_) {
314             canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, rectItemWidth, rectItemWidth });
315         } else if (rectItemHeight < rectItemWidth) {
316             canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, rectItemHeight, rectItemHeight });
317         } else {
318             float customPointX = axis_ == Axis::HORIZONTAL ? center.GetX() : center.GetY();
319             float customPointY = axis_ == Axis::HORIZONTAL ? center.GetY() : center.GetX();
320             canvas.DrawCircle({ customPointX, customPointY }, rectItemHeight * 0.5);
321         }
322     } else {
323         float pointX = axis_ == Axis::HORIZONTAL ? center.GetX() : center.GetY();
324         float pointY = axis_ == Axis::HORIZONTAL ? center.GetY() : center.GetX();
325         canvas.DrawCircle({ pointX, pointY }, itemHalfSizes[ITEM_HALF_HEIGHT]);
326     }
327     canvas.DetachBrush();
328 }
329 
PaintSelectedIndicator(RSCanvas & canvas,const OffsetF & leftCenter,const OffsetF & rightCenter,const LinearVector<float> & itemHalfSizes,bool isOverlong)330 void DotIndicatorModifier::PaintSelectedIndicator(RSCanvas& canvas, const OffsetF& leftCenter,
331     const OffsetF& rightCenter, const LinearVector<float>& itemHalfSizes, bool isOverlong)
332 {
333     RSBrush brush;
334     brush.SetAntiAlias(true);
335     brush.SetColor(ToRSColor(originalSelectColor_));
336     canvas.AttachBrush(brush);
337 
338     auto selectedItemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
339     if (isCustomSize_ && !isOverlong) {
340         selectedItemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * HALF_FLOAT;
341     }
342 
343     float rectLeft = (axis_ == Axis::HORIZONTAL ? leftCenter.GetX() - selectedItemHalfWidth
344                                                 : leftCenter.GetY() - itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT]);
345 
346     float rectTop = (axis_ == Axis::HORIZONTAL ? leftCenter.GetY() - itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT]
347                                                : leftCenter.GetX() - selectedItemHalfWidth);
348     float rectRight = (axis_ == Axis::HORIZONTAL ? rightCenter.GetX() + selectedItemHalfWidth
349                                                  : rightCenter.GetY() + itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT]);
350 
351     float rectBottom = (axis_ == Axis::HORIZONTAL ? rightCenter.GetY() + itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT]
352                                                   : rightCenter.GetX() + selectedItemHalfWidth);
353 
354     float rectSelectedItemWidth = selectedItemHalfWidth * TWO_FLOAT;
355     float rectSelectedItemHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT] * TWO_FLOAT;
356 
357     if (rectSelectedItemHeight > rectSelectedItemWidth && !isCustomSize_) {
358         canvas.DrawRoundRect(
359             { { rectLeft, rectTop, rectRight, rectBottom }, rectSelectedItemWidth, rectSelectedItemWidth });
360     } else {
361         canvas.DrawRoundRect(
362             { { rectLeft, rectTop, rectRight, rectBottom }, rectSelectedItemHeight, rectSelectedItemHeight });
363     }
364     canvas.DetachBrush();
365 }
366 
PaintMask(DrawingContext & context)367 void DotIndicatorModifier::PaintMask(DrawingContext& context)
368 {
369     RSCanvas& canvas = context.canvas;
370 
371     RSBrush brush;
372     brush.SetAntiAlias(true);
373     canvas.Save();
374 
375     std::vector<RSColorQuad> colors;
376     colors.push_back(0x00000000);
377     colors.push_back(0xff000000);
378     colors.push_back(0xff000000);
379 
380     RSPoint startPt = { offset_.GetX(), offset_.GetY() };
381     RSPoint endPt = { offset_.GetX(), offset_.GetY() };
382     startPt -= axis_ == Axis::HORIZONTAL ? RSPoint(0, (9.0_vp).ConvertToPx()) : RSPoint((9.0_vp).ConvertToPx(), 0);
383     endPt += axis_ == Axis::HORIZONTAL ? RSPoint(0, (15.0_vp).ConvertToPx()) : RSPoint((15.0_vp).ConvertToPx(), 0);
384 
385     std::vector<float> pos = { 0.0f, 0.75f, 1.0f };
386 
387     brush.SetShaderEffect(RSShaderEffect::CreateLinearGradient(startPt, endPt, colors, pos, RSTileMode::CLAMP));
388     canvas.DrawRect({ startPt.GetX(), startPt.GetY(), endPt.GetX(), endPt.GetY() });
389 }
390 
UpdateShrinkPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)391 void DotIndicatorModifier::UpdateShrinkPaintProperty(
392     const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
393     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
394 {
395     indicatorMargin_->Set(margin);
396     indicatorPadding_->Set(static_cast<float>(paddingSide_.ConvertToPx()));
397 
398     if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
399         vectorBlackPointCenterX_->Set(vectorBlackPointCenterX);
400         longPointLeftCenterX_->Set(longPointCenterX.first);
401         longPointRightCenterX_->Set(longPointCenterX.second);
402     }
403 
404     itemHalfSizes_->Set(normalItemHalfSizes);
405     normalToHoverPointDilateRatio_->Set(1.0f);
406     hoverToNormalPointDilateRatio_->Set(1.0f);
407     longPointDilateRatio_->Set(1.0f);
408     backgroundWidthDilateRatio_->Set(1.0f);
409     backgroundHeightDilateRatio_->Set(1.0f);
410 }
411 
UpdateDilatePaintProperty(const LinearVector<float> & hoverItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)412 void DotIndicatorModifier::UpdateDilatePaintProperty(
413     const LinearVector<float>& hoverItemHalfSizes, const LinearVector<float>& vectorBlackPointCenterX,
414     const std::pair<float, float>& longPointCenterX)
415 {
416     indicatorMargin_->Set({ 0, 0 });
417     indicatorPadding_->Set(static_cast<float>(paddingSide_.ConvertToPx()));
418 
419     vectorBlackPointCenterX_->Set(vectorBlackPointCenterX);
420     if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
421         longPointLeftCenterX_->Set(longPointCenterX.first);
422         longPointRightCenterX_->Set(longPointCenterX.second);
423     }
424     itemHalfSizes_->Set(hoverItemHalfSizes);
425     backgroundWidthDilateRatio_->Set(1.0f);
426     backgroundHeightDilateRatio_->Set(1.0f);
427 }
428 
UpdateBackgroundColor(const Color & backgroundColor)429 void DotIndicatorModifier::UpdateBackgroundColor(const Color& backgroundColor)
430 {
431     backgroundColor_->Set(LinearColor(backgroundColor));
432 }
433 
UpdateNormalPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)434 void DotIndicatorModifier::UpdateNormalPaintProperty(
435     const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
436     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
437 {
438     auto swiperTheme = GetSwiperIndicatorTheme();
439     CHECK_NULL_VOID(swiperTheme);
440     auto backgroundColor = indicatorMask_ ?
441         swiperTheme->GetPressedColor() :
442         swiperTheme->GetHoverColor().ChangeOpacity(0);
443     UpdateShrinkPaintProperty(margin, normalItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
444     UpdateBackgroundColor(backgroundColor);
445 }
446 
UpdateHoverPaintProperty(const LinearVector<float> & hoverItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)447 void DotIndicatorModifier::UpdateHoverPaintProperty(
448     const LinearVector<float>& hoverItemHalfSizes,
449     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
450 {
451     auto swiperTheme = GetSwiperIndicatorTheme();
452     CHECK_NULL_VOID(swiperTheme);
453     auto backgroundColor = swiperTheme->GetHoverColor();
454     UpdateDilatePaintProperty(hoverItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
455     UpdateBackgroundColor(backgroundColor);
456 }
457 
UpdatePressPaintProperty(const LinearVector<float> & hoverItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)458 void DotIndicatorModifier::UpdatePressPaintProperty(
459     const LinearVector<float>& hoverItemHalfSizes,
460     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
461 {
462     auto swiperTheme = GetSwiperIndicatorTheme();
463     CHECK_NULL_VOID(swiperTheme);
464     auto backgroundColor = swiperTheme->GetPressedColor();
465     UpdateDilatePaintProperty(hoverItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
466     UpdateBackgroundColor(backgroundColor);
467 }
468 
UpdateNormalToHoverPaintProperty(const LinearVector<float> & hoverItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)469 void DotIndicatorModifier::UpdateNormalToHoverPaintProperty(
470     const LinearVector<float>& hoverItemHalfSizes, const LinearVector<float>& vectorBlackPointCenterX,
471     const std::pair<float, float>& longPointCenterX)
472 {
473     AnimationOption option;
474     option.SetDuration(COMPONENT_DILATE_ANIMATION_DURATION);
475     option.SetCurve(Curves::SHARP);
476     longPointLeftAnimEnd_ = true;
477     longPointRightAnimEnd_ = true;
478     AnimationUtils::Animate(option, [weak = WeakClaim(this), hoverItemHalfSizes, vectorBlackPointCenterX,
479         longPointCenterX]() {
480         auto modifier = weak.Upgrade();
481         CHECK_NULL_VOID(modifier);
482         modifier->UpdateHoverPaintProperty(hoverItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
483     });
484 }
485 
UpdateHoverToNormalPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)486 void DotIndicatorModifier::UpdateHoverToNormalPaintProperty(
487     const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
488     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
489 {
490     AnimationOption option;
491     option.SetDuration(COMPONENT_SHRINK_ANIMATION_DURATION);
492     option.SetCurve(Curves::SHARP);
493     longPointLeftAnimEnd_ = true;
494     longPointRightAnimEnd_ = true;
495     AnimationUtils::Animate(option, [weak = WeakClaim(this), margin, normalItemHalfSizes, vectorBlackPointCenterX,
496         longPointCenterX]() {
497         auto modifier = weak.Upgrade();
498         CHECK_NULL_VOID(modifier);
499         modifier->UpdateNormalPaintProperty(margin, normalItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
500     });
501 }
502 
UpdateNormalToPressPaintProperty(const LinearVector<float> & hoverItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)503 void DotIndicatorModifier::UpdateNormalToPressPaintProperty(
504     const LinearVector<float>& hoverItemHalfSizes, const LinearVector<float>& vectorBlackPointCenterX,
505     const std::pair<float, float>& longPointCenterX)
506 {
507     AnimationOption option;
508     option.SetDuration(COMPONENT_DILATE_ANIMATION_DURATION);
509     option.SetCurve(Curves::SHARP);
510     longPointLeftAnimEnd_ = true;
511     longPointRightAnimEnd_ = true;
512     AnimationUtils::Animate(option, [weak = WeakClaim(this), hoverItemHalfSizes, vectorBlackPointCenterX,
513         longPointCenterX]() {
514         auto modifier = weak.Upgrade();
515         CHECK_NULL_VOID(modifier);
516         modifier->UpdatePressPaintProperty(hoverItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
517     });
518 }
519 
UpdatePressToNormalPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)520 void DotIndicatorModifier::UpdatePressToNormalPaintProperty(
521     const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
522     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
523 {
524     AnimationOption option;
525     option.SetDuration(COMPONENT_SHRINK_ANIMATION_DURATION);
526     option.SetCurve(Curves::SHARP);
527     AnimationUtils::Animate(option, [weak = WeakClaim(this), margin, normalItemHalfSizes, vectorBlackPointCenterX,
528         longPointCenterX]() {
529         auto modifier = weak.Upgrade();
530         CHECK_NULL_VOID(modifier);
531         modifier->UpdateNormalPaintProperty(margin, normalItemHalfSizes, vectorBlackPointCenterX, longPointCenterX);
532     });
533 }
534 
UpdateHoverAndPressConversionPaintProperty()535 void DotIndicatorModifier::UpdateHoverAndPressConversionPaintProperty()
536 {
537     auto swiperTheme = GetSwiperIndicatorTheme();
538     CHECK_NULL_VOID(swiperTheme);
539     Color backgroundColor = isPressed_ ? swiperTheme->GetPressedColor() : swiperTheme->GetHoverColor();
540     AnimationOption option;
541     option.SetDuration(MOUSE_PRESS_ANIMATION_DURATION);
542     option.SetCurve(Curves::SHARP);
543     AnimationUtils::Animate(option, [weak = WeakClaim(this), backgroundColor]() {
544         auto modifier = weak.Upgrade();
545         CHECK_NULL_VOID(modifier);
546         modifier->UpdateBackgroundColor(backgroundColor);
547     });
548 }
549 
UpdateNormalToHoverPointDilateRatio()550 void DotIndicatorModifier::UpdateNormalToHoverPointDilateRatio()
551 {
552     normalToHoverPointDilateRatio_->Set(1.0f);
553     AnimationOption option;
554     option.SetDuration(POINT_HOVER_ANIMATION_DURATION);
555     option.SetCurve(Curves::SHARP);
556     AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
557         auto modifier = weak.Upgrade();
558         CHECK_NULL_VOID(modifier);
559         modifier->normalToHoverPointDilateRatio_->Set(modifier->scaleIndicator_);
560     });
561 }
562 
UpdateHoverToNormalPointDilateRatio()563 void DotIndicatorModifier::UpdateHoverToNormalPointDilateRatio()
564 {
565     hoverToNormalPointDilateRatio_->Set(normalToHoverPointDilateRatio_->Get());
566     AnimationOption option;
567     option.SetDuration(POINT_HOVER_ANIMATION_DURATION);
568     option.SetCurve(Curves::SHARP);
569     AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
570         auto modifier = weak.Upgrade();
571         CHECK_NULL_VOID(modifier);
572         modifier->hoverToNormalPointDilateRatio_->Set(1.0f);
573     });
574 }
575 
UpdateLongPointDilateRatio()576 void DotIndicatorModifier::UpdateLongPointDilateRatio()
577 {
578     AnimationOption option;
579     option.SetDuration(POINT_HOVER_ANIMATION_DURATION);
580     option.SetCurve(Curves::SHARP);
581     if (longPointIsHover_) {
582         AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
583             auto modifier = weak.Upgrade();
584             CHECK_NULL_VOID(modifier);
585             modifier->longPointDilateRatio_->Set(modifier->scaleIndicator_);
586         });
587     } else {
588         AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
589             auto modifier = weak.Upgrade();
590             CHECK_NULL_VOID(modifier);
591             modifier->longPointDilateRatio_->Set(1.0f);
592         });
593     }
594 }
595 
UpdateAllPointCenterXAnimation(GestureState gestureState,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX)596 void DotIndicatorModifier::UpdateAllPointCenterXAnimation(GestureState gestureState,
597     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX)
598 {
599     AnimationOption blackPointOption;
600     blackPointOption.SetDuration(BLACK_POINT_DURATION);
601     blackPointOption.SetCurve(AceType::MakeRefPtr<CubicCurve>(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY,
602         CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING));
603     AnimationUtils::Animate(blackPointOption, [weak = WeakClaim(this), vectorBlackPointCenterX]() {
604         auto modifier = weak.Upgrade();
605         CHECK_NULL_VOID(modifier);
606         modifier->vectorBlackPointCenterX_->Set(vectorBlackPointCenterX);
607     });
608 
609     // normal page turning
610     AnimationOption optionHead;
611     RefPtr<Curve> curve = headCurve_;
612     optionHead.SetCurve(curve);
613     optionHead.SetDuration(animationDuration_);
614 
615     AnimationOption optionTail;
616     optionTail.SetCurve(GetTailCurve());
617     optionTail.SetDuration(animationDuration_);
618     AnimationOption optionLeft = optionTail;
619     AnimationOption optionRight = optionHead;
620 
621     if (gestureState == GestureState::GESTURE_STATE_RELEASE_LEFT) {
622         optionLeft = optionHead;
623         optionRight = optionTail;
624     }
625 
626     if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
627         longPointLeftAnimEnd_ = false;
628         longPointRightAnimEnd_ = false;
629         auto weak = WeakClaim(this);
630         AnimationUtils::StartAnimation(optionLeft, [weak, longPointCenterX]() {
631                 auto modifier = weak.Upgrade();
632                 CHECK_NULL_VOID(modifier);
633                 modifier->longPointLeftCenterX_->Set(longPointCenterX.first);
634             }, [weak]() {
635                 auto modifier = weak.Upgrade();
636                 CHECK_NULL_VOID(modifier);
637                 modifier->longPointLeftAnimEnd_ = true;
638             });
639 
640         AnimationUtils::StartAnimation(optionRight, [weak, longPointCenterX]() {
641                 auto modifier = weak.Upgrade();
642                 CHECK_NULL_VOID(modifier);
643                 modifier->longPointRightCenterX_->Set(longPointCenterX.second);
644             }, [weak]() {
645                 auto modifier = weak.Upgrade();
646                 CHECK_NULL_VOID(modifier);
647                 modifier->longPointRightAnimEnd_ = true;
648             });
649     }
650 }
651 
UpdateTouchBottomAnimation(TouchBottomType touchBottomType,const LinearVector<float> & vectorBlackPointCenterX,const std::pair<float,float> & longPointCenterX,float touchBottomRate)652 void DotIndicatorModifier::UpdateTouchBottomAnimation(TouchBottomType touchBottomType,
653     const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX,
654     float touchBottomRate)
655 {
656     AnimationOption option;
657     option.SetDuration(POINT_HOVER_ANIMATION_DURATION);
658     option.SetCurve(AceType::MakeRefPtr<CubicCurve>(TOUCH_BOTTOM_CURVE_VELOCITY, TOUCH_BOTTOM_CURVE_MASS,
659         TOUCH_BOTTOM_CURVE_STIFFNESS, TOUCH_BOTTOM_CURVE_DAMPING));
660 
661     auto backgroundWidthDilateRatio = 1.0f;
662     auto backgroundHeightDilateRatio = 1.0f;
663 
664     if (touchBottomType != TouchBottomType::NONE) {
665         backgroundWidthDilateRatio = TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE -
666                                      TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE * vectorBlackPointCenterX_->Get().size();
667         backgroundHeightDilateRatio = TOUCH_BOTTOM_BACKGROUND_HEIGHT_MULTIPLE;
668         backgroundWidthDilateRatio = (backgroundWidthDilateRatio - 1.0f) * touchBottomRate + 1.0f;
669         backgroundHeightDilateRatio = (backgroundHeightDilateRatio - 1.0f) * touchBottomRate + 1.0f;
670     }
671     touchBottomType_ = touchBottomType;
672     AnimationUtils::Animate(option, [weak = WeakClaim(this), backgroundWidthDilateRatio, backgroundHeightDilateRatio,
673                                         vectorBlackPointCenterX, longPointCenterX]() {
674         auto modifier = weak.Upgrade();
675         CHECK_NULL_VOID(modifier);
676         modifier->backgroundWidthDilateRatio_->Set(backgroundWidthDilateRatio);
677         modifier->backgroundHeightDilateRatio_->Set(backgroundHeightDilateRatio);
678         modifier->vectorBlackPointCenterX_->Set(vectorBlackPointCenterX);
679         if (modifier->longPointLeftAnimEnd_) {
680             modifier->longPointLeftCenterX_->Set(longPointCenterX.first);
681         }
682         if (modifier->longPointRightAnimEnd_) {
683             modifier->longPointRightCenterX_->Set(longPointCenterX.second);
684         }
685     });
686 }
687 
PlayBlackPointsAnimation(const LinearVector<float> & vectorBlackPointCenterX)688 void DotIndicatorModifier::PlayBlackPointsAnimation(const LinearVector<float>& vectorBlackPointCenterX)
689 {
690     auto curve = AceType::MakeRefPtr<CubicCurve>(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS,
691         CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING);
692     AnimationOption option;
693     option.SetCurve(curve);
694     option.SetDuration(animationDuration_);
695     AnimationUtils::StartAnimation(option, [weak = WeakClaim(this), vectorBlackPointCenterX]() {
696         auto modifier = weak.Upgrade();
697         CHECK_NULL_VOID(modifier);
698         modifier->vectorBlackPointCenterX_->Set(vectorBlackPointCenterX);
699     });
700 }
701 
PlayOpacityAnimation()702 void DotIndicatorModifier::PlayOpacityAnimation()
703 {
704     AnimationOption optionOpacity;
705     // x0:0.33, y0:0, x1:0.67, y1:1
706     optionOpacity.SetCurve(AceType::MakeRefPtr<CubicCurve>(0.33, 0, 0.67, 1));
707     optionOpacity.SetDuration(GetLoopOpacityDuration());
708     isSelectedColorAnimEnd_ = false;
709     isTouchBottomLoop_ = true;
710     selectedColor_->Set(LinearColor(selectedColor_->Get().BlendOpacity(0.0f)));
711     auto weak = WeakClaim(this);
712     AnimationUtils::StartAnimation(optionOpacity, [weak]() {
713             auto modifier = weak.Upgrade();
714             CHECK_NULL_VOID(modifier);
715             auto color = modifier->selectedColor_->Get();
716             auto targetColor =
717                 LinearColor(Color::FromARGB(TARGET_ALPHA, color.GetRed(), color.GetGreen(), color.GetBlue()));
718             modifier->selectedColor_->Set(targetColor);
719             modifier->touchBottomPointColor_->Set(LinearColor(modifier->touchBottomPointColor_->Get().BlendOpacity(0)));
720         }, [weak]() {
721             auto modifier = weak.Upgrade();
722             CHECK_NULL_VOID(modifier);
723             modifier->touchBottomPointColor_->Set(LinearColor(modifier->unselectedColor_->Get()));
724             modifier->isTouchBottomLoop_ = false;
725             modifier->isSelectedColorAnimEnd_ = true;
726         });
727 }
728 
GetLoopTranslateDuration() const729 int32_t DotIndicatorModifier::GetLoopTranslateDuration() const
730 {
731     if (InstanceOf<InterpolatingSpring>(headCurve_)) {
732         return DEFAULT_TOUCH_BOTTOM_ANIMATION_DURATION;
733     }
734 
735     return static_cast<int32_t>(static_cast<float>(animationDuration_) * LOOP_TRANSLATE_DURATION_PERCENT);
736 }
737 
GetLoopOpacityDuration() const738 int32_t DotIndicatorModifier::GetLoopOpacityDuration() const
739 {
740     if (InstanceOf<InterpolatingSpring>(headCurve_)) {
741         return DEFAULT_OPACITY_ANIMATION_DURATION;
742     }
743 
744     return static_cast<int32_t>(static_cast<float>(animationDuration_) * LOOP_OPACITY_DURATION_PERCENT);
745 }
746 
PlayTouchBottomAnimation(const std::vector<std::pair<float,float>> & longPointCenterX,TouchBottomTypeLoop touchBottomTypeLoop,const LinearVector<float> & vectorBlackPointCenterX)747 void DotIndicatorModifier::PlayTouchBottomAnimation(const std::vector<std::pair<float, float>>& longPointCenterX,
748     TouchBottomTypeLoop touchBottomTypeLoop, const LinearVector<float>& vectorBlackPointCenterX)
749 {
750     if (vectorBlackPointCenterX.empty()) {
751         return;
752     }
753 
754     AnimationOption optionBottom;
755     // x0:0.33, y0:0, x1:0.67, y1:1
756     optionBottom.SetCurve(AceType::MakeRefPtr<CubicCurve>(0.33, 0, 0.67, 1));
757     optionBottom.SetDuration(GetLoopTranslateDuration());
758 
759     auto weak = WeakClaim(this);
760     FinishCallback bottomFinishCallback = [weak, optionBottom, longPointCenterX, vectorBlackPointCenterX,
761                                               touchBottomTypeLoop]() {
762         auto modifier = weak.Upgrade();
763         CHECK_NULL_VOID(modifier);
764         modifier->animationState_ = TouchBottomAnimationStage::STAGE_NONE;
765         if (!(modifier->ifNeedFinishCallback_)) {
766             return;
767         }
768         modifier->animationState_ = TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT;
769         modifier->PlayOpacityAnimation();
770         if (touchBottomTypeLoop == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
771             modifier->longPointLeftCenterX_->Set(vectorBlackPointCenterX[vectorBlackPointCenterX.size() - 1]);
772             modifier->longPointRightCenterX_->Set(vectorBlackPointCenterX[vectorBlackPointCenterX.size() - 1]);
773         } else if (touchBottomTypeLoop == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
774             modifier->longPointLeftCenterX_->Set(vectorBlackPointCenterX[0]);
775             modifier->longPointRightCenterX_->Set(vectorBlackPointCenterX[0]);
776         }
777 
778         AnimationUtils::StartAnimation(optionBottom, [weak, longPointCenterX]() {
779             auto modifier = weak.Upgrade();
780             CHECK_NULL_VOID(modifier);
781             modifier->longPointRightCenterX_->Set(longPointCenterX[1].second);
782             if (modifier->isCustomSize_) {
783                 modifier->longPointLeftCenterX_->Set(longPointCenterX[1].second);
784             } else {
785                 modifier->longPointLeftCenterX_->Set(longPointCenterX[1].first);
786             }
787         }, [weak]() {
788             auto modifier = weak.Upgrade();
789             CHECK_NULL_VOID(modifier);
790             modifier->longPointLeftAnimEnd_ = true;
791             modifier->longPointRightAnimEnd_ = true;
792             modifier->isBottomAnimationFinished_ = true;
793             modifier->animationState_ = TouchBottomAnimationStage::STAGE_NONE;
794         });
795     };
796     if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
797         longPointLeftAnimEnd_ = false;
798         longPointRightAnimEnd_ = false;
799         ifNeedFinishCallback_ = true;
800         isBottomAnimationFinished_ = false;
801         animationState_ = TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT;
802         touchBottomPointColor_->Set(LinearColor(selectedColor_->Get()));
803         AnimationUtils::StartAnimation(optionBottom, [weak, longPointCenterX]() {
804             auto modifier = weak.Upgrade();
805             CHECK_NULL_VOID(modifier);
806             modifier->longPointLeftCenterX_->Set(longPointCenterX[0].first);
807             modifier->longPointRightCenterX_->Set(longPointCenterX[0].second);
808             modifier->bottomCenterX_ = longPointCenterX[1];
809         }, bottomFinishCallback);
810     }
811 }
812 
CalculateMinimumAmplitudeRatio(const std::vector<std::pair<float,float>> & longPointCenterX,GestureState gestureState) const813 float DotIndicatorModifier::CalculateMinimumAmplitudeRatio(
814     const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState) const
815 {
816     auto minimumAmplitudeRatio =
817         NearEqual(longPointCenterX[0].first, longPointLeftCenterX_->Get())
818             ? InterpolatingSpring::DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO
819             : DEFAULT_MINIMUM_AMPLITUDE_PX / std::abs(longPointCenterX[0].first - longPointLeftCenterX_->Get());
820     if (gestureState == GestureState::GESTURE_STATE_RELEASE_LEFT) {
821         minimumAmplitudeRatio =
822             NearEqual(longPointCenterX[0].second, longPointRightCenterX_->Get())
823                 ? InterpolatingSpring::DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO
824                 : DEFAULT_MINIMUM_AMPLITUDE_PX / std::abs(longPointCenterX[0].second - longPointRightCenterX_->Get());
825     }
826     return std::max(minimumAmplitudeRatio, InterpolatingSpring::DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO);
827 }
828 
GetTailCurve()829 RefPtr<InterpolatingSpring> DotIndicatorModifier::GetTailCurve()
830 {
831     auto step = std::abs(currentIndex_ - currentIndexActual_);
832     if (step == LONG_POINT_STEP_TWO) {
833         return LONG_POINT_STEP_TWO_CURVE;
834     }
835 
836     if (step == LONG_POINT_STEP_THREE) {
837         return LONG_POINT_STEP_THREE_CURVE;
838     }
839 
840     if (step == LONG_POINT_STEP_FOUR) {
841         return LONG_POINT_STEP_FOUR_CURVE;
842     }
843 
844     if (step > LONG_POINT_STEP_FOUR) {
845         return LONG_POINT_STEP_FIVE_CURVE;
846     }
847 
848     return LONG_POINT_DEFAULT_CURVE;
849 }
850 
CreateTailOption(const std::vector<std::pair<float,float>> & longPointCenterX,GestureState gestureState,bool isNormal)851 AnimationOption DotIndicatorModifier::CreateTailOption(
852     const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState, bool isNormal)
853 {
854     AnimationOption optionTail;
855     optionTail.SetDuration(animationDuration_);
856 
857     if (userSetSwiperCurve_) {
858         optionTail.SetCurve(headCurve_);
859         return optionTail;
860     }
861 
862     auto interpolatingSpring = GetTailCurve();
863     if (isNormal) {
864         interpolatingSpring->UpdateMinimumAmplitudeRatio(
865             CalculateMinimumAmplitudeRatio(longPointCenterX, gestureState));
866     }
867     optionTail.SetCurve(interpolatingSpring);
868     return optionTail;
869 }
870 
PlayLongPointAnimation(const std::vector<std::pair<float,float>> & longPointCenterX,GestureState gestureState,TouchBottomTypeLoop touchBottomTypeLoop,const LinearVector<float> & vectorBlackPointCenterX,bool isNormal)871 void DotIndicatorModifier::PlayLongPointAnimation(const std::vector<std::pair<float, float>>& longPointCenterX,
872     GestureState gestureState, TouchBottomTypeLoop touchBottomTypeLoop,
873     const LinearVector<float>& vectorBlackPointCenterX, bool isNormal)
874 {
875     if (longPointCenterX.empty()) {
876         return;
877     }
878     // touch bottom
879     if (longPointCenterX.size() > 1) {
880         PlayTouchBottomAnimation(longPointCenterX, touchBottomTypeLoop, vectorBlackPointCenterX);
881         return;
882     }
883     // normal page turning
884     AnimationOption optionHead;
885     RefPtr<Curve> curve = headCurve_;
886     optionHead.SetCurve(curve);
887     optionHead.SetDuration(animationDuration_);
888 
889     AnimationOption optionTail = CreateTailOption(longPointCenterX, gestureState, isNormal);
890     AnimationOption optionLeft = optionTail;
891     AnimationOption optionRight = optionHead;
892 
893     if (gestureState == GestureState::GESTURE_STATE_RELEASE_LEFT) {
894         optionLeft = optionHead;
895         optionRight = optionTail;
896     }
897 
898     if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
899         longPointLeftAnimEnd_ = false;
900         longPointRightAnimEnd_ = false;
901         auto weak = WeakClaim(this);
902         AnimationUtils::StartAnimation(optionLeft, [weak, longPointCenterX]() {
903                 auto modifier = weak.Upgrade();
904                 CHECK_NULL_VOID(modifier);
905                 modifier->longPointLeftCenterX_->Set(longPointCenterX[0].first);
906             }, [weak]() {
907                 auto modifier = weak.Upgrade();
908                 CHECK_NULL_VOID(modifier);
909                 modifier->longPointLeftAnimEnd_ = true;
910             });
911 
912         AnimationUtils::StartAnimation(optionRight, [weak, longPointCenterX]() {
913                 auto modifier = weak.Upgrade();
914                 CHECK_NULL_VOID(modifier);
915                 modifier->longPointRightCenterX_->Set(longPointCenterX[0].second);
916             }, [weak]() {
917                 auto modifier = weak.Upgrade();
918                 CHECK_NULL_VOID(modifier);
919                 modifier->longPointRightAnimEnd_ = true;
920             });
921     }
922 }
923 
PlayIndicatorAnimation(const LinearVector<float> & vectorBlackPointCenterX,const std::vector<std::pair<float,float>> & longPointCenterX,GestureState gestureState,TouchBottomTypeLoop touchBottomTypeLoop)924 void DotIndicatorModifier::PlayIndicatorAnimation(const LinearVector<float>& vectorBlackPointCenterX,
925     const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState,
926     TouchBottomTypeLoop touchBottomTypeLoop)
927 {
928     StopAnimation();
929     isTouchBottomLoop_ = false;
930     animationState_ = TouchBottomAnimationStage::STAGE_NONE;
931     PlayBlackPointsAnimation(vectorBlackPointCenterX);
932     PlayLongPointAnimation(longPointCenterX, gestureState, touchBottomTypeLoop, vectorBlackPointCenterX);
933 }
934 
FinishAnimationToTargetImmediately(std::pair<float,float> centerX)935 void DotIndicatorModifier::FinishAnimationToTargetImmediately(std::pair<float, float> centerX)
936 {
937     AnimationOption option;
938     option.SetDuration(0);
939     option.SetCurve(Curves::LINEAR);
940     AnimationUtils::StartAnimation(option, [weak = WeakClaim(this), centerX]() {
941         auto modifier = weak.Upgrade();
942         CHECK_NULL_VOID(modifier);
943         modifier->isBottomAnimationFinished_ = true;
944         modifier->ifNeedFinishCallback_ = false;
945         modifier->longPointRightCenterX_->Set(centerX.second);
946         if (modifier->isCustomSize_) {
947             modifier->longPointLeftCenterX_->Set(centerX.second);
948         } else {
949             modifier->longPointLeftCenterX_->Set(centerX.first);
950         }
951     });
952 }
953 
StopAnimation(bool ifImmediately)954 void DotIndicatorModifier::StopAnimation(bool ifImmediately)
955 {
956     if (ifImmediately) {
957         AnimationOption option;
958         option.SetDuration(0);
959         option.SetCurve(Curves::LINEAR);
960         AnimationUtils::StartAnimation(option, [weak = WeakClaim(this)]() {
961             auto modifier = weak.Upgrade();
962             CHECK_NULL_VOID(modifier);
963             modifier->ifNeedFinishCallback_ = false;
964             modifier->animationState_ = TouchBottomAnimationStage::STAGE_NONE;
965             modifier->longPointLeftCenterX_->Set(modifier->longPointLeftCenterX_->Get());
966             modifier->longPointRightCenterX_->Set(modifier->longPointRightCenterX_->Get());
967         });
968     }
969     AnimationOption option;
970     option.SetDuration(0);
971     option.SetCurve(Curves::LINEAR);
972     AnimationUtils::StartAnimation(option, [weak = WeakClaim(this)]() {
973         auto modifier = weak.Upgrade();
974         CHECK_NULL_VOID(modifier);
975         modifier->vectorBlackPointCenterX_->Set(modifier->vectorBlackPointCenterX_->Get());
976     });
977     longPointLeftAnimEnd_ = true;
978     longPointRightAnimEnd_ = true;
979     ifNeedFinishCallback_ = false;
980 }
981 } // namespace OHOS::Ace::NG
982