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