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