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