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