• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/loading_progress/loading_progress_modifier.h"
17 #include <algorithm>
18 
19 #include "base/geometry/dimension.h"
20 #include "base/memory/ace_type.h"
21 #include "base/utils/utils.h"
22 #include "bridge/common/dom/dom_type.h"
23 #include "core/components/common/properties/animation_option.h"
24 #include "core/components_ng/base/modifier.h"
25 #include "core/components_ng/pattern/loading_progress/loading_progress_utill.h"
26 #include "core/components_ng/pattern/refresh/refresh_animation_state.h"
27 #include "core/components_ng/render/animation_utils.h"
28 #include "core/components_ng/render/drawing.h"
29 #include "core/components_ng/render/drawing_prop_convertor.h"
30 #include "core/components_ng/render/paint.h"
31 
32 namespace OHOS::Ace::NG {
33 namespace {
34 constexpr float TOTAL_ANGLE = 360.0f;
35 constexpr float ROTATEX = -116.0f;
36 constexpr float ROTATEY = 30.0f;
37 constexpr float ROTATEZ = 22.0f;
38 constexpr float COUNT = 50.0f;
39 constexpr float HALF = 0.5f;
40 constexpr float DOUBLE = 2.0f;
41 constexpr int32_t RING_ALPHA = 200;
42 constexpr int32_t TOTAL_POINTS_COUNT = 20;
43 constexpr int32_t TAIL_ANIAMTION_DURATION = 400;
44 constexpr int32_t TRANS_DURATION = 100;
45 constexpr float TOTAL_TAIL_LENGTH = 60.0f;
46 constexpr float TAIL_ALPHA_RATIO = 0.82f;
47 constexpr float INITIAL_SIZE_SCALE = 0.825f;
48 constexpr float INITIAL_OPACITY_SCALE = 0.7f;
49 constexpr float COMET_TAIL_ANGLE = 3.0f;
50 constexpr int32_t LOADING_DURATION = 1200;
51 constexpr float FOLLOW_START = 72.0f;
52 constexpr float FOLLOW_SPAN = 10.0f;
53 constexpr float FULL_COUNT = 100.0f;
54 constexpr float STAGE1 = 0.25f;
55 constexpr float STAGE2 = 0.65f;
56 constexpr float STAGE3 = 0.75f;
57 constexpr float STAGE4 = 0.85f;
58 constexpr float STAGE5 = 1.0f;
59 constexpr float OPACITY1 = 0.2f;
60 constexpr float OPACITY2 = 0.7f;
61 constexpr float OPACITY3 = 1.0f;
62 constexpr float SIZE_SCALE1 = 0.65f;
63 constexpr float SIZE_SCALE2 = 0.825f;
64 constexpr float SIZE_SCALE3 = 0.93f;
65 constexpr float MOVE_STEP = 0.06f;
66 constexpr float TRANS_OPACITY_SPAN = 0.3f;
67 constexpr float FULL_OPACITY = 255.0f;
68 constexpr float TWO = 2.0f;
69 } // namespace
LoadingProgressModifier(LoadingProgressOwner loadingProgressOwner)70 LoadingProgressModifier::LoadingProgressModifier(LoadingProgressOwner loadingProgressOwner)
71     : date_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f)),
72       color_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::BLUE)),
73       centerDeviation_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f)),
74       cometOpacity_(AceType::MakeRefPtr<AnimatablePropertyFloat>(INITIAL_OPACITY_SCALE)),
75       cometSizeScale_(AceType::MakeRefPtr<AnimatablePropertyFloat>(INITIAL_SIZE_SCALE)),
76       cometTailLen_(AceType::MakeRefPtr<AnimatablePropertyFloat>(TOTAL_TAIL_LENGTH)),
77       sizeScale_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1.0f)),
78       loadingProgressOwner_(loadingProgressOwner)
79 {
80     AttachProperty(date_);
81     AttachProperty(color_);
82     AttachProperty(centerDeviation_);
83     AttachProperty(cometOpacity_);
84     AttachProperty(cometSizeScale_);
85     AttachProperty(cometTailLen_);
86     AttachProperty(sizeScale_);
87 };
88 
onDraw(DrawingContext & context)89 void LoadingProgressModifier::onDraw(DrawingContext& context)
90 {
91     float date = date_->Get();
92     auto diameter = std::min(context.width, context.height);
93     RingParam ringParam;
94     ringParam.strokeWidth = LoadingProgressUtill::GetRingStrokeWidth(diameter) * sizeScale_->Get();
95     ringParam.radius = LoadingProgressUtill::GetRingRadius(diameter) * sizeScale_->Get();
96     ringParam.movement =
97         (ringParam.radius * DOUBLE + ringParam.strokeWidth) * centerDeviation_->Get() * sizeScale_->Get();
98 
99     CometParam cometParam;
100     cometParam.radius = LoadingProgressUtill::GetCometRadius(diameter) * sizeScale_->Get();
101     cometParam.alphaScale = cometOpacity_->Get();
102     cometParam.sizeScale = cometSizeScale_->Get();
103     cometParam.pointCount = GetCometNumber();
104 
105     auto orbitRadius = LoadingProgressUtill::GetOrbitRadius(diameter) * sizeScale_->Get();
106     if (date > COUNT) {
107         DrawRing(context, ringParam);
108         DrawOrbit(context, cometParam, orbitRadius, date);
109     } else {
110         DrawOrbit(context, cometParam, orbitRadius, date);
111         DrawRing(context, ringParam);
112     }
113 }
114 
DrawRing(DrawingContext & context,const RingParam & ringParam)115 void LoadingProgressModifier::DrawRing(DrawingContext& context, const RingParam& ringParam)
116 {
117     auto& canvas = context.canvas;
118     canvas.Save();
119     RSPen pen;
120     auto ringColor = color_->Get();
121     pen.SetColor(ToRSColor(Color::FromARGB(RING_ALPHA, ringColor.GetRed(), ringColor.GetGreen(), ringColor.GetBlue())));
122     pen.SetWidth(ringParam.strokeWidth);
123     pen.SetAntiAlias(true);
124     canvas.AttachPen(pen);
125     canvas.DrawCircle({ context.width * HALF, context.height * HALF + ringParam.movement }, ringParam.radius);
126     canvas.DetachPen();
127     canvas.Restore();
128 }
129 
DrawOrbit(DrawingContext & context,const CometParam & cometParam,float orbitRadius,float date)130 void LoadingProgressModifier::DrawOrbit(
131     DrawingContext& context, const CometParam& cometParam, float orbitRadius, float date)
132 {
133     auto pointCounts = cometParam.pointCount;
134     auto& canvas = context.canvas;
135     float width_ = context.width;
136     float height_ = context.height;
137     double angle = TOTAL_ANGLE * date / FULL_COUNT;
138     auto* camera_ = new RSCamera3D();
139     camera_->Save();
140     camera_->RotateYDegrees(ROTATEY);
141     camera_->RotateXDegrees(ROTATEX);
142     camera_->RotateZDegrees(ROTATEZ);
143     RSMatrix matrix;
144     camera_->ApplyToMatrix(matrix);
145     camera_->Restore();
146     auto center = RSPoint(width_ / 2, height_ / 2);
147     RSBrush brush;
148     brush.SetAntiAlias(true);
149     canvas.Save();
150     canvas.Translate(center.GetX(), center.GetY());
151     std::vector<RSPoint> points;
152     for (uint32_t i = 0; i < pointCounts; i++) {
153         RSPoint point;
154         float cometAngal = GetCurentCometAngle(angle, pointCounts - i, pointCounts);
155         float rad = cometAngal * PI_NUM / (TOTAL_ANGLE * HALF);
156         point.SetX(std::cos(rad) * orbitRadius);
157         point.SetY(-std::sin(rad) * orbitRadius);
158         points.push_back(point);
159     }
160     std::vector<RSPoint> distPoints(points.size());
161     matrix.MapPoints(distPoints, points, points.size());
162     auto cometColor = color_->Get();
163     float colorAlpha = cometColor.GetAlpha() / FULL_OPACITY;
164     auto baseAlpha = colorAlpha * cometParam.alphaScale;
165     for (uint32_t i = 0; i < distPoints.size(); i++) {
166         RSPoint pointCenter = distPoints[i];
167         float setAlpha = GetCurentCometOpacity(baseAlpha, distPoints.size() - i, distPoints.size());
168         if (NearZero(setAlpha)) {
169             continue;
170         }
171         brush.SetColor(
172             ToRSColor(Color::FromRGBO(cometColor.GetRed(), cometColor.GetGreen(), cometColor.GetBlue(), setAlpha)));
173         canvas.AttachBrush(brush);
174         canvas.DrawCircle(pointCenter, cometParam.radius * cometParam.sizeScale);
175     }
176     canvas.DetachBrush();
177     canvas.Restore();
178 }
179 
StartRecycleRingAnimation()180 void LoadingProgressModifier::StartRecycleRingAnimation()
181 {
182     auto context = PipelineBase::GetCurrentContext();
183     CHECK_NULL_VOID(context);
184     auto previousStageCurve = AceType::MakeRefPtr<CubicCurve>(0.0f, 0.0f, 0.67f, 1.0f);
185     AnimationOption option;
186     option.SetDuration(LOADING_DURATION);
187     option.SetCurve(previousStageCurve);
188     if (context->IsFormRender()) {
189         LOGI("LoadingProgress is restricted at runtime when form render");
190         option.SetIteration(1);
191     } else {
192         option.SetIteration(-1);
193     }
194     AnimationUtils::OpenImplicitAnimation(option, previousStageCurve, nullptr);
195     auto middleStageCurve = AceType::MakeRefPtr<CubicCurve>(0.33f, 0.0f, 0.67f, 1.0f);
196     AnimationUtils::AddKeyFrame(STAGE1, middleStageCurve, [&]() { centerDeviation_->Set(-1 * MOVE_STEP); });
197     auto latterStageCurve = AceType::MakeRefPtr<CubicCurve>(0.33f, 0.0f, 1.0f, 1.0f);
198     AnimationUtils::AddKeyFrame(STAGE3, latterStageCurve, [&]() { centerDeviation_->Set(MOVE_STEP); });
199     AnimationUtils::AddKeyFrame(STAGE5, latterStageCurve, [&]() { centerDeviation_->Set(0.0f); });
200     AnimationUtils::CloseImplicitAnimation();
201 }
202 
StartRecycleCometAnimation()203 void LoadingProgressModifier::StartRecycleCometAnimation()
204 {
205     auto context = PipelineBase::GetCurrentContext();
206     CHECK_NULL_VOID(context);
207     auto curve = AceType::MakeRefPtr<LinearCurve>();
208     AnimationOption option;
209     option.SetDuration(LOADING_DURATION);
210     option.SetCurve(curve);
211     if (context->IsFormRender()) {
212         LOGI("LoadingProgress is restricted at runtime when form render");
213         option.SetIteration(1);
214     } else {
215         option.SetIteration(-1);
216     }
217 
218     cometOpacity_->Set(OPACITY2);
219     AnimationUtils::OpenImplicitAnimation(option, curve, nullptr);
220     AnimationUtils::AddKeyFrame(STAGE1, curve, [&]() {
221         cometOpacity_->Set(OPACITY1);
222         cometSizeScale_->Set(SIZE_SCALE1);
223     });
224     AnimationUtils::AddKeyFrame(STAGE2, curve, [&]() {
225         cometOpacity_->Set(OPACITY3);
226         cometSizeScale_->Set(SIZE_SCALE3);
227     });
228     AnimationUtils::AddKeyFrame(STAGE3, curve, [&]() {
229         cometOpacity_->Set(OPACITY3);
230         cometSizeScale_->Set(1.0f);
231     });
232     AnimationUtils::AddKeyFrame(STAGE4, curve, [&]() {
233         cometOpacity_->Set(OPACITY3);
234         cometSizeScale_->Set(SIZE_SCALE3);
235     });
236     AnimationUtils::AddKeyFrame(STAGE5, curve, [&]() {
237         cometOpacity_->Set(OPACITY2);
238         cometSizeScale_->Set(SIZE_SCALE2);
239     });
240     AnimationUtils::CloseImplicitAnimation();
241 }
242 
StartCometTailAnimation()243 void LoadingProgressModifier::StartCometTailAnimation()
244 {
245     auto curve = AceType::MakeRefPtr<LinearCurve>();
246     AnimationOption option;
247     option.SetDuration(TAIL_ANIAMTION_DURATION);
248     option.SetIteration(1);
249     option.SetCurve(curve);
250     AnimationUtils::Animate(option, [&]() { cometTailLen_->Set(TOTAL_TAIL_LENGTH); });
251 }
252 
GetCurentCometOpacity(float baseOpacity,uint32_t index,uint32_t totalNumber)253 float LoadingProgressModifier::GetCurentCometOpacity(float baseOpacity, uint32_t index, uint32_t totalNumber)
254 {
255     return baseOpacity * std::pow(TAIL_ALPHA_RATIO, std::clamp(index, 1u, totalNumber) - 1);
256 }
257 
GetCurentCometAngle(float baseAngle,uint32_t index,uint32_t totalNumber)258 float LoadingProgressModifier::GetCurentCometAngle(float baseAngle, uint32_t index, uint32_t totalNumber)
259 {
260     return std::fmod((baseAngle - (std::clamp(index, 1u, totalNumber) - 1) * COMET_TAIL_ANGLE), TOTAL_ANGLE);
261 }
262 
GetCometNumber()263 uint32_t LoadingProgressModifier::GetCometNumber()
264 {
265     CHECK_NULL_RETURN(cometTailLen_, TOTAL_POINTS_COUNT);
266     return static_cast<uint32_t>(cometTailLen_->Get() / COMET_TAIL_ANGLE);
267 }
268 
StartRecycle()269 void LoadingProgressModifier::StartRecycle()
270 {
271     auto context = PipelineBase::GetCurrentContext();
272     CHECK_NULL_VOID(context);
273     if (isLoading_) {
274         return;
275     }
276     sizeScale_->Set(1.0f);
277     if (date_) {
278         isLoading_ = true;
279         date_->Set(0.0f);
280         AnimationOption option = AnimationOption();
281         RefPtr<Curve> curve = AceType::MakeRefPtr<LinearCurve>();
282         option.SetDuration(LOADING_DURATION);
283         option.SetDelay(0);
284         option.SetCurve(curve);
285         if (context->IsFormRender()) {
286             LOGI("LoadingProgress is restricted at runtime when form render");
287             option.SetIteration(1);
288         } else {
289             option.SetIteration(-1);
290         }
291 
292         AnimationUtils::Animate(option, [&]() { date_->Set(FULL_COUNT); });
293     }
294     cometOpacity_->Set(INITIAL_OPACITY_SCALE);
295     cometSizeScale_->Set(INITIAL_SIZE_SCALE);
296     StartRecycleRingAnimation();
297     StartRecycleCometAnimation();
298 }
299 
StartTransToRecycleAnimation()300 void LoadingProgressModifier::StartTransToRecycleAnimation()
301 {
302     auto curve = AceType::MakeRefPtr<CubicCurve>(0.6f, 0.2f, 1.0f, 1.0f);
303     AnimationOption option;
304     option.SetDuration(TRANS_DURATION);
305     option.SetIteration(1);
306     option.SetCurve(curve);
307     AnimationUtils::Animate(
308         option,
309         [&]() {
310             date_->Set(FULL_COUNT);
311             cometOpacity_->Set(1.0 - TRANS_OPACITY_SPAN);
312             cometSizeScale_->Set(INITIAL_SIZE_SCALE);
313         },
314         [&]() { StartRecycle(); });
315     StartCometTailAnimation();
316 }
317 
ChangeRefreshFollowData(float refreshFollowRatio)318 void LoadingProgressModifier::ChangeRefreshFollowData(float refreshFollowRatio)
319 {
320     auto ratio = CorrectNormalize(refreshFollowRatio);
321     sizeScale_->Set(std::sqrt(TWO) * HALF + (1.0 - std::sqrt(TWO) * HALF) * ratio);
322     if (isLoading_) {
323         return;
324     }
325     CHECK_NULL_VOID(date_);
326     date_->Set(FOLLOW_START + FOLLOW_SPAN * ratio);
327     cometTailLen_->Set(COMET_TAIL_ANGLE);
328     cometOpacity_->Set(1.0f);
329     cometSizeScale_->Set(1.0f);
330 }
331 
CorrectNormalize(float originData)332 float LoadingProgressModifier::CorrectNormalize(float originData)
333 {
334     auto ratio = originData;
335     if (ratio < 0.0f) {
336         ratio = 0.0f;
337     }
338     if (ratio > 1.0f) {
339         ratio = 1.0f;
340     };
341     return ratio;
342 }
343 } // namespace OHOS::Ace::NG
344