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