1 /*
2 * Copyright (c) 2024 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 #include "core/components_ng/manager/drag_drop/utils/drag_animation_helper.h"
16
17 #include "core/components_ng/manager/drag_drop/drag_drop_func_wrapper.h"
18 #include "core/components_ng/manager/drag_drop/drag_drop_controller_func_wrapper.h"
19 #include "core/components_ng/pattern/image/image_pattern.h"
20 #include "core/components_ng/pattern/menu/menu_theme.h"
21 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
22 #include "core/components_ng/pattern/stack/stack_pattern.h"
23 #include "core/components_ng/pattern/text/text_pattern.h"
24
25 namespace OHOS::Ace::NG {
26 namespace {
27 constexpr int32_t BEFORE_LIFTING_TIME = 650;
28 constexpr int32_t IMAGE_SHOW_TIME = 50;
29 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 300;
30 constexpr int32_t BADGE_ANIMATION_DURATION = 200;
31 constexpr int32_t BADGE_ANIMATION_DELAY = 100;
32 constexpr int32_t NODE_RESET_DURATION = 200;
33 constexpr float DEFAULT_ANIMATION_SCALE = 0.95f;
34 constexpr float GATHER_SPRING_RESPONSE = 0.304f;
35 constexpr float GATHER_SPRING_DAMPING_FRACTION = 0.97f;
36 constexpr float GRID_MOVE_SCALE = 0.2f;
37 constexpr float LIST_MOVE_SCALE = 0.2f;
38 constexpr float EULER_NUMBER = 2.71828f;
39 constexpr float GATHER_OFFSET_RADIUS = 0.1f;
40 constexpr float PIXELMAP_DRAG_SCALE_MULTIPLE = 1.05f;
41 constexpr float BADGE_ANIMATION_SCALE = 1.0f;
42 constexpr Dimension BADGE_RELATIVE_OFFSET = 8.0_vp;
43 constexpr Dimension BADGE_DEFAULT_SIZE = 24.0_vp;
44 constexpr Dimension BADGE_TEXT_FONT_SIZE = 14.0_fp;
45 const Color BADGE_TEXT_FONT_COLOR = Color::FromString("#ffffffff");
46 const Color BADGE_BACKGROUND_COLOR = Color::FromString("#ff007dff");
47 constexpr float DEFAULT_INTERPOLATING_SPRING_VELOCITY = 10.0f;
48 constexpr float DEFAULT_INTERPOLATING_SPRING_MASS = 1.0f;
49 constexpr float DEFAULT_INTERPOLATING_SPRING_STIFFNESS = 410.0f;
50 constexpr float DEFAULT_INTERPOLATING_SPRING_DAMPING = 38.0f;
51 constexpr float DEFAULT_GRAYED = 0.4f;
52 constexpr float HALF_DIVIDE = 2.0f;
53 const RefPtr<InterpolatingSpring> DRAG_START_ANIMATION_CURVE =
54 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 0.0f, 380.0f, 34.0f);
55 const RefPtr<InterpolatingSpring> DRAG_END_ANIMATION_CURVE =
56 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 0.0f, 228.0f, 29.0f);
57 const RefPtr<Curve> DRAG_CONTROL_ANIMATION_CURVE =
58 AceType::MakeRefPtr<ResponsiveSpringMotion>(0.347f, 0.99f, 0.0f);
59 }
60
CalcDistanceBeforeLifting(bool isGrid,CalcResult & calcResult,OffsetF gatherNodeCenter,const std::vector<GatherNodeChildInfo> & gatherNodeChildrenInfo)61 void DragAnimationHelper::CalcDistanceBeforeLifting(bool isGrid, CalcResult& calcResult, OffsetF gatherNodeCenter,
62 const std::vector<GatherNodeChildInfo>& gatherNodeChildrenInfo)
63 {
64 for (const auto& child : gatherNodeChildrenInfo) {
65 auto imageNode = child.imageNode.Upgrade();
66 CHECK_NULL_VOID(imageNode);
67 auto width = child.width;
68 auto height = child.height;
69 OffsetF curPos = {child.offset.GetX() + child.halfWidth, child.offset.GetY() + child.halfHeight};
70 float dis = sqrt(pow(gatherNodeCenter.GetX() - curPos.GetX(), 2) +
71 pow(gatherNodeCenter.GetY() - curPos.GetY(), 2));
72 calcResult.maxDistance = std::max(calcResult.maxDistance, dis);
73 calcResult.minDistance = calcResult.minDistance < 0 ? dis : std::min(calcResult.minDistance, dis);
74 if (isGrid) {
75 calcResult.maxTranslation = calcResult.maxTranslation < 0 ? std::min(width, height) :
76 std::min(calcResult.maxTranslation, std::min(width, height));
77 } else {
78 calcResult.maxTranslation = calcResult.maxTranslation < 0 ? height :
79 std::min(calcResult.maxTranslation, height);
80 }
81 }
82 calcResult.maxTranslation *= isGrid ? GRID_MOVE_SCALE : LIST_MOVE_SCALE;
83 }
84
CalcOffsetToTarget(OffsetF curPos,OffsetF targetPos,CalcResult & calcResult)85 OffsetF DragAnimationHelper::CalcOffsetToTarget(OffsetF curPos, OffsetF targetPos, CalcResult& calcResult)
86 {
87 if (NearZero(calcResult.maxDistance) || NearZero(calcResult.minDistance) || calcResult.maxTranslation < 0) {
88 return { 0.0f, 0.0f };
89 }
90
91 float xDis = targetPos.GetX() - curPos.GetX();
92 float yDis = targetPos.GetY() - curPos.GetY();
93 float dis = sqrt(pow(xDis, 2) + pow(yDis, 2));
94 if (NearZero(dis)) {
95 return { 0.0f, 0.0f };
96 }
97 auto trans = calcResult.maxTranslation * pow(EULER_NUMBER, -(dis - calcResult.minDistance) /
98 calcResult.maxDistance * GATHER_OFFSET_RADIUS);
99 float x = xDis * trans / dis;
100 float y = yDis * trans / dis;
101 return { x, y };
102 }
103
PlayGatherNodeTranslateAnimation(const RefPtr<FrameNode> & frameNode,const RefPtr<OverlayManager> & overlayManager)104 void DragAnimationHelper::PlayGatherNodeTranslateAnimation(const RefPtr<FrameNode>& frameNode,
105 const RefPtr<OverlayManager>& overlayManager)
106 {
107 CHECK_NULL_VOID(overlayManager);
108 CHECK_NULL_VOID(frameNode);
109 AnimationOption option;
110 option.SetDuration(BEFORE_LIFTING_TIME);
111 option.SetCurve(Curves::SHARP);
112 auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenterToScreen(frameNode);
113 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
114
115 bool isGrid = frameNode->GetTag() == V2::GRID_ITEM_ETS_TAG;
116 CalcResult calcResult = { 0.0f, -1.0f, -1.0f };
117 CalcDistanceBeforeLifting(isGrid, calcResult, gatherNodeCenter, gatherNodeChildrenInfo);
118 AnimationUtils::Animate(
119 option,
120 [gatherNodeCenter, gatherNodeChildrenInfo, calcResult]() mutable {
121 for (const auto& child : gatherNodeChildrenInfo) {
122 auto imageNode = child.imageNode.Upgrade();
123 auto curPos = child.offset + OffsetF(child.halfWidth, child.halfHeight);
124 auto offset = CalcOffsetToTarget(curPos, gatherNodeCenter, calcResult);
125 offset += child.offset;
126 DragDropFuncWrapper::UpdateNodePositionToScreen(imageNode, offset);
127 }
128 });
129 }
130
PlayGatherNodeOpacityAnimation(const RefPtr<OverlayManager> & overlayManager)131 void DragAnimationHelper::PlayGatherNodeOpacityAnimation(const RefPtr<OverlayManager>& overlayManager)
132 {
133 CHECK_NULL_VOID(overlayManager);
134 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
135
136 AnimationOption opacityOption;
137 opacityOption.SetDuration(IMAGE_SHOW_TIME);
138 opacityOption.SetCurve(AceType::MakeRefPtr<CubicCurve>(0.0f, 0.0f, 1.0f, 1.0f));
139
140 for (const auto& child : gatherNodeChildrenInfo) {
141 auto imageNode = child.imageNode.Upgrade();
142 CHECK_NULL_VOID(imageNode);
143 auto imageContext = imageNode->GetRenderContext();
144 CHECK_NULL_VOID(imageContext);
145 imageContext->OpacityAnimation(opacityOption, 0.0f, 1.0f);
146 }
147 }
148
PlayGatherAnimationBeforeLifting(const RefPtr<DragEventActuator> & actuator)149 void DragAnimationHelper::PlayGatherAnimationBeforeLifting(const RefPtr<DragEventActuator>& actuator)
150 {
151 TAG_LOGI(AceLogTag::ACE_DRAG, "Play gather animation before lifting");
152 CHECK_NULL_VOID(actuator);
153 if (!actuator->IsNeedGather()) {
154 return;
155 }
156 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
157 CHECK_NULL_VOID(pipeline);
158 auto manager = pipeline->GetOverlayManager();
159 CHECK_NULL_VOID(manager);
160 auto frameNode = actuator->GetFrameNode();
161 CHECK_NULL_VOID(frameNode);
162 auto gatherNode = actuator->GetGatherNode();
163 CHECK_NULL_VOID(gatherNode);
164 auto imageContext = gatherNode->GetRenderContext();
165 CHECK_NULL_VOID(imageContext);
166 imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
167 auto gatherNodeChildrenInfo = actuator->GetGatherNodeChildrenInfo();
168 DragEventActuator::MountGatherNode(manager, frameNode, gatherNode, gatherNodeChildrenInfo);
169 actuator->ClearGatherNodeChildrenInfo();
170 actuator->InitGatherNodesPosition(gatherNodeChildrenInfo);
171 pipeline->FlushSyncGeometryNodeTasks();
172 manager->SetIsGatherWithMenu(false);
173 PlayGatherNodeOpacityAnimation(manager);
174 PlayGatherNodeTranslateAnimation(frameNode, manager);
175 }
176
PlayNodeAnimationBeforeLifting(const RefPtr<FrameNode> & frameNode)177 void DragAnimationHelper::PlayNodeAnimationBeforeLifting(const RefPtr<FrameNode>& frameNode)
178 {
179 CHECK_NULL_VOID(frameNode);
180 auto previewOptions = frameNode->GetDragPreviewOption();
181 if (!previewOptions.defaultAnimationBeforeLifting) {
182 return;
183 }
184 AnimationOption option;
185 option.SetDuration(BEFORE_LIFTING_TIME);
186 auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(DEFAULT_INTERPOLATING_SPRING_VELOCITY,
187 DEFAULT_INTERPOLATING_SPRING_MASS, DEFAULT_INTERPOLATING_SPRING_STIFFNESS,
188 DEFAULT_INTERPOLATING_SPRING_DAMPING);
189 option.SetCurve(springCurve);
190 auto renderContext = frameNode->GetRenderContext();
191 CHECK_NULL_VOID(renderContext);
192 renderContext->UpdateTransformScale({ 1.0f, 1.0f });
193
194 AnimationUtils::Animate(
195 option,
196 [renderContext]() mutable {
197 CHECK_NULL_VOID(renderContext);
198 renderContext->UpdateTransformScale({ DEFAULT_ANIMATION_SCALE, DEFAULT_ANIMATION_SCALE });
199 });
200 }
201
PlayNodeResetAnimation(const RefPtr<DragEventActuator> & actuator)202 void DragAnimationHelper::PlayNodeResetAnimation(const RefPtr<DragEventActuator>& actuator)
203 {
204 CHECK_NULL_VOID(actuator);
205 auto frameNode = actuator->GetFrameNode();
206 CHECK_NULL_VOID(frameNode);
207 bool defaultAnimationBeforeLifting = frameNode->GetDragPreviewOption().defaultAnimationBeforeLifting;
208 if (!defaultAnimationBeforeLifting) {
209 return;
210 }
211 auto frameContext = frameNode->GetRenderContext();
212 CHECK_NULL_VOID(frameContext);
213 auto layoutProperty = frameNode->GetLayoutProperty();
214 if (layoutProperty) {
215 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
216 }
217 AnimationOption option;
218 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
219 const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.33f, 0.67f, 1.0f);
220 option.SetCurve(curve);
221 AnimationUtils::Animate(
222 option,
223 [frameContext]() mutable {
224 frameContext->UpdateTransformScale({ 1.0f, 1.0f });
225 },
226 option.GetOnFinishEvent());
227 }
228
PlayGatherAnimation(const RefPtr<FrameNode> & frameNode,const RefPtr<OverlayManager> & overlayManager)229 void DragAnimationHelper::PlayGatherAnimation(const RefPtr<FrameNode>& frameNode,
230 const RefPtr<OverlayManager>& overlayManager)
231 {
232 TAG_LOGI(AceLogTag::ACE_DRAG, "Play gather animation");
233 CHECK_NULL_VOID(frameNode);
234 auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenter(frameNode);
235 CHECK_NULL_VOID(overlayManager);
236 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
237 BorderRadiusProperty borderRadius;
238 borderRadius.SetRadius(0.0_vp);
239 borderRadius.multiValued = false;
240 for (const auto& child : gatherNodeChildrenInfo) {
241 auto imageNode = child.imageNode.Upgrade();
242 CHECK_NULL_VOID(imageNode);
243 auto imageContext = imageNode->GetRenderContext();
244 CHECK_NULL_VOID(imageContext);
245 imageContext->UpdateBorderRadius(borderRadius);
246 }
247
248 AnimationOption option;
249 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
250 const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(GATHER_SPRING_RESPONSE,
251 GATHER_SPRING_DAMPING_FRACTION, 0.0f);
252 option.SetCurve(curve);
253 auto geometryNode = frameNode->GetGeometryNode();
254 CHECK_NULL_VOID(geometryNode);
255 auto frameNodeSize = geometryNode->GetFrameSize();
256 auto renderContext = frameNode->GetRenderContext();
257 CHECK_NULL_VOID(renderContext);
258 GatherAnimationInfo gatherAnimationInfo = { PIXELMAP_DRAG_SCALE_MULTIPLE, frameNodeSize.Width(),
259 frameNodeSize.Height(), gatherNodeCenter, renderContext->GetBorderRadius() };
260 AnimationUtils::Animate(
261 option,
262 [weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager)), gatherAnimationInfo,
263 weak = AceType::WeakClaim(AceType::RawPtr(frameNode))]() {
264 auto overlayManager = weakOverlayManager.Upgrade();
265 auto frameNode = weak.Upgrade();
266 DragDropManager::UpdateGatherNodeAttr(overlayManager, gatherAnimationInfo);
267 DragDropManager::UpdateGatherNodePosition(overlayManager, frameNode);
268 },
269 option.GetOnFinishEvent());
270 }
271
ShowBadgeAnimation(const RefPtr<FrameNode> & textNode)272 void DragAnimationHelper::ShowBadgeAnimation(const RefPtr<FrameNode>& textNode)
273 {
274 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
275 CHECK_NULL_VOID(pipelineContext);
276 auto dragDropManager = pipelineContext->GetDragDropManager();
277 CHECK_NULL_VOID(dragDropManager);
278 CHECK_NULL_VOID(textNode);
279 auto textNodeContext = textNode->GetRenderContext();
280 CHECK_NULL_VOID(textNodeContext);
281 textNodeContext->SetVisible(true);
282 auto windowScale = dragDropManager->GetWindowScale();
283 auto badgeScale = GreatNotEqual(windowScale, 0.0f) ? BADGE_ANIMATION_SCALE / windowScale : BADGE_ANIMATION_SCALE;
284 if (!dragDropManager->IsShowBadgeAnimation()) {
285 textNodeContext->UpdateTransformScale({ badgeScale, badgeScale });
286 return;
287 }
288 textNodeContext->UpdateTransformScale({ 0.0f, 0.0f });
289 RefPtr<Curve> interpolatingSpring = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 628.0f, 40.0f);
290 CHECK_NULL_VOID(interpolatingSpring);
291 AnimationOption textOption;
292 textOption.SetDuration(BADGE_ANIMATION_DURATION);
293 textOption.SetCurve(interpolatingSpring);
294 textOption.SetDelay(BADGE_ANIMATION_DELAY);
295 AnimationUtils::Animate(
296 textOption,
297 [textNodeContext, badgeScale]() mutable {
298 textNodeContext->UpdateTransformScale({ badgeScale, badgeScale });
299 },
300 textOption.GetOnFinishEvent());
301
302 dragDropManager->SetIsShowBadgeAnimation(false);
303 }
304
CalcBadgeTextOffset(const RefPtr<MenuPattern> & menuPattern,const RefPtr<FrameNode> & imageNode,const RefPtr<PipelineBase> & context,int32_t badgeLength)305 OffsetF DragAnimationHelper::CalcBadgeTextOffset(const RefPtr<MenuPattern>& menuPattern,
306 const RefPtr<FrameNode>& imageNode, const RefPtr<PipelineBase>& context, int32_t badgeLength)
307 {
308 CHECK_NULL_RETURN(imageNode, OffsetF());
309 CHECK_NULL_RETURN(menuPattern, OffsetF());
310 auto offset = imageNode->GetPaintRectOffset();
311 auto width = imageNode->GetGeometryNode()->GetFrameSize().Width();
312 auto scaleAfter = menuPattern->GetPreviewAfterAnimationScale();
313 auto menuTheme = context->GetTheme<NG::MenuTheme>();
314 CHECK_NULL_RETURN(menuTheme, OffsetF());
315 auto previewAfterAnimationScale =
316 LessNotEqual(scaleAfter, 0.0) ? menuTheme->GetPreviewAfterAnimationScale() : scaleAfter;
317 double textOffsetX = offset.GetX() + width * previewAfterAnimationScale -
318 BADGE_RELATIVE_OFFSET.ConvertToPx() - (BADGE_RELATIVE_OFFSET.ConvertToPx() * badgeLength);
319 double textOffsetY = offset.GetY() - BADGE_RELATIVE_OFFSET.ConvertToPx();
320 return OffsetF(textOffsetX, textOffsetY);
321 }
322
CalcBadgeTextPosition(const RefPtr<MenuPattern> & menuPattern,const RefPtr<OverlayManager> & manager,const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & textNode)323 void DragAnimationHelper::CalcBadgeTextPosition(const RefPtr<MenuPattern>& menuPattern,
324 const RefPtr<OverlayManager>& manager, const RefPtr<FrameNode>& imageNode, const RefPtr<FrameNode>& textNode)
325 {
326 CHECK_NULL_VOID(manager);
327 CHECK_NULL_VOID(textNode);
328 CHECK_NULL_VOID(menuPattern);
329 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
330 CHECK_NULL_VOID(pipelineContext);
331 auto dragDropManager = pipelineContext->GetDragDropManager();
332 CHECK_NULL_VOID(dragDropManager);
333 auto frameNode = FrameNode::GetFrameNode(menuPattern->GetTargetTag(), menuPattern->GetTargetId());
334 CHECK_NULL_VOID(frameNode);
335 auto badgeNumber = frameNode->GetDragPreviewOption().GetCustomerBadgeNumber();
336 auto childSize = badgeNumber.has_value() ? static_cast<size_t>(badgeNumber.value()) :
337 manager->GetGatherNodeChildrenInfo().size() + 1;
338 TAG_LOGI(AceLogTag::ACE_DRAG, "Badge node number %{public}d, children count %{public}d",
339 badgeNumber.value_or(-1), static_cast<int32_t>(manager->GetGatherNodeChildrenInfo().size()));
340 auto badgeLength = std::to_string(childSize).size();
341 UpdateBadgeLayoutAndRenderContext(textNode, badgeLength, childSize);
342 auto textRenderContext = textNode->GetRenderContext();
343 CHECK_NULL_VOID(textRenderContext);
344 auto offset = CalcBadgeTextOffset(menuPattern, imageNode, pipelineContext, badgeLength);
345 textRenderContext->UpdatePosition(OffsetT<Dimension>(Dimension(offset.GetX()), Dimension(offset.GetY())));
346 textNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
347 textNode->MarkModifyDone();
348 textNode->SetLayoutDirtyMarked(true);
349 textNode->SetActive(true);
350 auto context = textNode->GetContext();
351 if (context) {
352 context->FlushUITaskWithSingleDirtyNode(textNode);
353 }
354 pipelineContext->FlushSyncGeometryNodeTasks();
355 }
356
UpdateBadgeLayoutAndRenderContext(const RefPtr<FrameNode> & textNode,int32_t badgeLength,int32_t childSize)357 void DragAnimationHelper::UpdateBadgeLayoutAndRenderContext(
358 const RefPtr<FrameNode>& textNode, int32_t badgeLength, int32_t childSize)
359 {
360 if (childSize <= 1) {
361 return;
362 }
363 CHECK_NULL_VOID(textNode);
364 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
365 CHECK_NULL_VOID(textLayoutProperty);
366 textLayoutProperty->UpdateContent(std::to_string(childSize));
367 textLayoutProperty->UpdateMaxLines(1);
368 textLayoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
369 textLayoutProperty->UpdateTextColor(BADGE_TEXT_FONT_COLOR);
370 textLayoutProperty->UpdateFontSize(BADGE_TEXT_FONT_SIZE);
371 textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
372 int64_t textWidth = BADGE_DEFAULT_SIZE.ConvertToPx() + (BADGE_RELATIVE_OFFSET.ConvertToPx() * (badgeLength - 1));
373 auto textSize = CalcSize(NG::CalcLength(textWidth), NG::CalcLength(BADGE_DEFAULT_SIZE.ConvertToPx()));
374 textLayoutProperty->UpdateUserDefinedIdealSize(textSize);
375
376 auto textRenderContext = textNode->GetRenderContext();
377 CHECK_NULL_VOID(textRenderContext);
378 textRenderContext->SetVisible(true);
379 textRenderContext->UpdateBackgroundColor(BADGE_BACKGROUND_COLOR);
380 BorderRadiusProperty borderRadius;
381 borderRadius.SetRadius(BADGE_DEFAULT_SIZE);
382 textRenderContext->UpdateBorderRadius(borderRadius);
383 }
384
UpdateGatherNodeToTop()385 void DragAnimationHelper::UpdateGatherNodeToTop()
386 {
387 auto mainPipeline = PipelineContext::GetMainPipelineContext();
388 CHECK_NULL_VOID(mainPipeline);
389 auto manager = mainPipeline->GetOverlayManager();
390 CHECK_NULL_VOID(manager);
391 manager->UpdateGatherNodeToTop();
392 }
393
ShowGatherAnimationWithMenu(const RefPtr<FrameNode> & menuWrapperNode)394 void DragAnimationHelper::ShowGatherAnimationWithMenu(const RefPtr<FrameNode>& menuWrapperNode)
395 {
396 auto mainPipeline = PipelineContext::GetMainPipelineContext();
397 CHECK_NULL_VOID(mainPipeline);
398 auto manager = mainPipeline->GetOverlayManager();
399 CHECK_NULL_VOID(manager);
400 manager->SetIsGatherWithMenu(true);
401
402 mainPipeline->AddAfterRenderTask([weakWrapperNode = AceType::WeakClaim(AceType::RawPtr(menuWrapperNode)),
403 weakManager = AceType::WeakClaim(AceType::RawPtr(manager))]() {
404 auto menuWrapperNode = weakWrapperNode.Upgrade();
405 CHECK_NULL_VOID(menuWrapperNode);
406 auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
407 CHECK_NULL_VOID(menuWrapperPattern);
408 auto manager = weakManager.Upgrade();
409 auto textNode = menuWrapperPattern->GetBadgeNode();
410 auto imageNode = menuWrapperPattern->GetPreview();
411 auto menuNode = menuWrapperPattern->GetMenu();
412 CHECK_NULL_VOID(menuNode);
413 auto menuPattern = menuNode->GetPattern<MenuPattern>();
414 DragAnimationHelper::PlayGatherAnimation(imageNode, manager);
415 DragAnimationHelper::CalcBadgeTextPosition(menuPattern, manager, imageNode, textNode);
416 DragAnimationHelper::ShowBadgeAnimation(textNode);
417 });
418 }
419
SetPreOpacity(const RefPtr<FrameNode> & preNode)420 void DragAnimationHelper::SetPreOpacity(const RefPtr<FrameNode>& preNode)
421 {
422 auto grayedOpacity = preNode->GetPreGrayedOpacity();
423 DoGrayedAnimation(preNode, grayedOpacity, DRAG_END_ANIMATION_CURVE);
424 }
425
DoDragStartGrayedAnimation(const RefPtr<FrameNode> & frameNode)426 void DragAnimationHelper::DoDragStartGrayedAnimation(const RefPtr<FrameNode>& frameNode)
427 {
428 CHECK_NULL_VOID(frameNode);
429 auto renderContext = frameNode->GetRenderContext();
430 CHECK_NULL_VOID(renderContext);
431 float opacity = 1.0f;
432 if (renderContext->HasOpacity()) {
433 opacity = renderContext->GetOpacityValue();
434 frameNode->SetPreGrayedOpacity(opacity);
435 }
436 DoGrayedAnimation(frameNode, opacity * DEFAULT_GRAYED, DRAG_START_ANIMATION_CURVE);
437 }
438
DoGrayedAnimation(const RefPtr<FrameNode> & frameNode,float opacity,RefPtr<InterpolatingSpring> cure)439 void DragAnimationHelper::DoGrayedAnimation(
440 const RefPtr<FrameNode>& frameNode, float opacity, RefPtr<InterpolatingSpring> cure)
441 {
442 CHECK_NULL_VOID(frameNode);
443 auto frameTag = frameNode->GetTag();
444 auto gestureHub = frameNode->GetOrCreateGestureEventHub();
445 CHECK_NULL_VOID(gestureHub);
446 if (gestureHub->IsTextCategoryComponent(frameTag)) {
447 return;
448 }
449 AnimationOption option;
450 option.SetCurve(cure);
451 AnimationUtils::Animate(
452 option, [frameNode, opacity]() { ACE_UPDATE_NODE_RENDER_CONTEXT(Opacity, opacity, frameNode); },
453 option.GetOnFinishEvent());
454 }
455
CreateImageNode(const RefPtr<PixelMap> & pixelMap)456 RefPtr<FrameNode> DragAnimationHelper::CreateImageNode(const RefPtr<PixelMap>& pixelMap)
457 {
458 CHECK_NULL_RETURN(pixelMap, nullptr);
459 auto width = pixelMap->GetWidth();
460 auto height = pixelMap->GetHeight();
461 auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
462 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
463 CHECK_NULL_RETURN(imageNode, nullptr);
464 auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
465 CHECK_NULL_RETURN(renderProps, nullptr);
466 renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
467 renderProps->UpdateNeedBorderRadius(false);
468 auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
469 CHECK_NULL_RETURN(props, nullptr);
470 props->UpdateAutoResize(false);
471 props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
472 auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
473 props->UpdateUserDefinedIdealSize(targetSize);
474 auto imageContext = imageNode->GetRenderContext();
475 CHECK_NULL_RETURN(imageContext, nullptr);
476 Vector5F rotate = Vector5F(0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
477 imageContext->UpdateTransformRotate(rotate);
478 imageContext->UpdateClipEdge(true);
479 imageContext->UpdateBorderRadius(BorderRadiusProperty(Dimension()));
480 imageContext->UpdateOpacity(1.0f);
481 auto imagePattern = imageNode->GetPattern<ImagePattern>();
482 if (imagePattern) {
483 imagePattern->SetSyncLoad(true);
484 }
485 ClickEffectInfo clickEffectInfo;
486 clickEffectInfo.level = ClickEffectLevel::LIGHT;
487 clickEffectInfo.scaleNumber = DEFAULT_ANIMATION_SCALE;
488 imageContext->UpdateClickEffectLevel(clickEffectInfo);
489 return imageNode;
490 }
491
CreateGatherNode(const RefPtr<FrameNode> & frameNode,std::vector<GatherNodeChildInfo> & gatherNodeInfo)492 RefPtr<FrameNode> DragAnimationHelper::CreateGatherNode(const RefPtr<FrameNode>& frameNode,
493 std::vector<GatherNodeChildInfo>& gatherNodeInfo)
494 {
495 CHECK_NULL_RETURN(frameNode, nullptr);
496 auto parentNode = DragDropFuncWrapper::FindItemParentNode(frameNode);
497 CHECK_NULL_RETURN(parentNode, nullptr);
498 auto scrollPattern = parentNode->GetPattern<ScrollablePattern>();
499 CHECK_NULL_RETURN(scrollPattern, nullptr);
500 auto children = scrollPattern->GetVisibleSelectedItems();
501 if (children.empty()) {
502 return nullptr;
503 }
504
505 auto stackNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
506 []() { return AceType::MakeRefPtr<StackPattern>(); });
507 CHECK_NULL_RETURN(stackNode, nullptr);
508 auto geometryNode = stackNode->GetGeometryNode();
509 CHECK_NULL_RETURN(geometryNode, nullptr);
510 geometryNode->SetFrameOffset({0.0f, 0.0f});
511 gatherNodeInfo.clear();
512 for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
513 auto itemFrameNode = (*iter);
514 if (itemFrameNode == frameNode) {
515 continue;
516 }
517 GatherNodeChildInfo gatherNodeChildInfo;
518 auto imageNode = CreateGatherImageNode(itemFrameNode, gatherNodeChildInfo);
519 CHECK_NULL_RETURN(imageNode, nullptr);
520 stackNode->AddChild(imageNode);
521 gatherNodeInfo.push_back(gatherNodeChildInfo);
522 }
523 TAG_LOGI(AceLogTag::ACE_DRAG, "Create gather node success, count %{public}d",
524 static_cast<int32_t>(children.size()));
525 return stackNode;
526 }
527
GetOrCreateGatherNode(const RefPtr<NG::OverlayManager> & overlayManager,const RefPtr<DragEventActuator> & actuator,std::vector<GatherNodeChildInfo> & info)528 RefPtr<FrameNode> DragAnimationHelper::GetOrCreateGatherNode(const RefPtr<NG::OverlayManager>& overlayManager,
529 const RefPtr<DragEventActuator>& actuator, std::vector<GatherNodeChildInfo>& info)
530 {
531 CHECK_NULL_RETURN(actuator, nullptr);
532 if (!actuator->IsNeedGather()) {
533 return nullptr;
534 }
535 auto frameNode = actuator->GetFrameNode();
536 CHECK_NULL_RETURN(frameNode, nullptr);
537 auto previewOptions = frameNode->GetDragPreviewOption();
538 if (!previewOptions.isMultiSelectionEnabled) {
539 return nullptr;
540 }
541 CHECK_NULL_RETURN(overlayManager, nullptr);
542 auto gatherNode = overlayManager->GetGatherNode();
543 if (!gatherNode) {
544 gatherNode = CreateGatherNode(frameNode, info);
545 if (gatherNode) {
546 MarkDirtyNode(gatherNode);
547 }
548 return gatherNode;
549 } else {
550 info = overlayManager->GetGatherNodeChildrenInfo();
551 overlayManager->RemoveGatherNode();
552 }
553 return gatherNode;
554 }
555
CreateGatherImageNode(const RefPtr<FrameNode> & frameNode,GatherNodeChildInfo & gatherNodeChildInfo)556 RefPtr<FrameNode> DragAnimationHelper::CreateGatherImageNode(const RefPtr<FrameNode>& frameNode,
557 GatherNodeChildInfo& gatherNodeChildInfo)
558 {
559 CHECK_NULL_RETURN(frameNode, nullptr);
560 auto pixelMap = DragDropFuncWrapper::GetGatherNodePreviewPixelMap(frameNode);
561 CHECK_NULL_RETURN(pixelMap, nullptr);
562 int32_t width = pixelMap->GetWidth();
563 int32_t height = pixelMap->GetHeight();
564 auto offset = DragDropFuncWrapper::GetPaintRectCenter(frameNode) - OffsetF(width / 2.0f, height / 2.0f);
565 auto imageNode = CreateImageNode(pixelMap);
566 CHECK_NULL_RETURN(imageNode, nullptr);
567 auto imageContext = imageNode->GetRenderContext();
568 CHECK_NULL_RETURN(imageContext, nullptr);
569 imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(offset.GetX()), Dimension(offset.GetY())));
570
571 gatherNodeChildInfo = { imageNode,
572 offset + DragDropFuncWrapper::GetCurrentWindowOffset(frameNode->GetContextRefPtr()), width, height,
573 width / 2.0f, height / 2.0f, WeakPtr<FrameNode>(frameNode) };
574 return imageNode;
575 }
576
MountGatherNode(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & gatherNode,const std::vector<GatherNodeChildInfo> & gatherNodeInfo)577 void DragAnimationHelper::MountGatherNode(const RefPtr<OverlayManager>& overlayManager,
578 const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& gatherNode,
579 const std::vector<GatherNodeChildInfo>& gatherNodeInfo)
580 {
581 if (!overlayManager || !frameNode || !gatherNode) {
582 return;
583 }
584 TAG_LOGI(AceLogTag::ACE_DRAG, "Mount gather node");
585 auto container = Container::Current();
586 if (container && container->IsScenceBoardWindow()) {
587 auto windowScene = overlayManager->FindWindowScene(frameNode);
588 overlayManager->MountGatherNodeToWindowScene(gatherNode, gatherNodeInfo, windowScene);
589 } else {
590 overlayManager->MountGatherNodeToRootNode(gatherNode, gatherNodeInfo);
591 }
592 }
593
MarkDirtyNode(const RefPtr<FrameNode> & frameNode)594 void DragAnimationHelper::MarkDirtyNode(const RefPtr<FrameNode>& frameNode)
595 {
596 CHECK_NULL_VOID(frameNode);
597 frameNode->MarkModifyDone();
598 frameNode->SetLayoutDirtyMarked(true);
599 auto context = frameNode->GetContext();
600 if (context) {
601 context->FlushUITaskWithSingleDirtyNode(frameNode);
602 }
603
604 auto children = frameNode->GetChildren();
605 for (const auto& child : children) {
606 CHECK_NULL_VOID(child);
607 auto imageNode = AceType::DynamicCast<FrameNode>(child);
608 CHECK_NULL_VOID(imageNode);
609 MarkDirtyNode(imageNode);
610 }
611 }
612
InitGatherNodeAttr(const RefPtr<FrameNode> & gatherNode,const std::vector<GatherNodeChildInfo> & gatherNodeInfo)613 void DragAnimationHelper::InitGatherNodeAttr(const RefPtr<FrameNode>& gatherNode,
614 const std::vector<GatherNodeChildInfo>& gatherNodeInfo)
615 {
616 CHECK_NULL_VOID(gatherNode);
617 auto renderContext = gatherNode->GetRenderContext();
618 if (renderContext) {
619 renderContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
620 }
621 for (auto childInfo : gatherNodeInfo) {
622 auto imageNode = childInfo.imageNode.Upgrade();
623 DragDropFuncWrapper::UpdateNodePositionToScreen(imageNode, childInfo.offset);
624 }
625 }
626
ShowGatherNodeAnimation(const RefPtr<FrameNode> & frameNode)627 bool DragAnimationHelper::ShowGatherNodeAnimation(const RefPtr<FrameNode>& frameNode)
628 {
629 TAG_LOGI(AceLogTag::ACE_DRAG, "Show gather node animation");
630 CHECK_NULL_RETURN(frameNode, false);
631 auto pipeline = frameNode->GetContextRefPtr();
632 CHECK_NULL_RETURN(pipeline, false);
633 auto manager = pipeline->GetOverlayManager();
634 CHECK_NULL_RETURN(manager, false);
635
636 if (manager->GetHasGatherNode()) {
637 TAG_LOGW(AceLogTag::ACE_DRAG, "Not need create gather node, already have");
638 return false;
639 }
640
641 //create gather node
642 std::vector<GatherNodeChildInfo> gatherNodeInfo;
643 auto gatherNode = CreateGatherNode(frameNode, gatherNodeInfo);
644 CHECK_NULL_RETURN(gatherNode, false);
645 MountGatherNode(manager, frameNode, gatherNode, gatherNodeInfo);
646 InitGatherNodeAttr(gatherNode, gatherNodeInfo);
647 AddDragNodeCopy(manager, frameNode, gatherNode);
648 MarkDirtyNode(gatherNode);
649
650 pipeline->FlushPipelineImmediately();
651 manager->SetIsGatherWithMenu(false);
652
653 //do gather animation before lifting
654 PlayGatherNodeOpacityAnimation(manager);
655 PlayGatherNodeTranslateAnimation(frameNode, manager);
656 ShowDragNodeCopyAnimation(manager, frameNode);
657 return true;
658 }
659
AddDragNodeCopy(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & gatherNode)660 void DragAnimationHelper::AddDragNodeCopy(const RefPtr<OverlayManager>& overlayManager,
661 const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& gatherNode)
662 {
663 CHECK_NULL_VOID(frameNode);
664 CHECK_NULL_VOID(gatherNode);
665 CHECK_NULL_VOID(overlayManager);
666 //create frameNode copy
667 auto renderContext = frameNode->GetRenderContext();
668 CHECK_NULL_VOID(renderContext);
669 auto pixelMap = renderContext->GetThumbnailPixelMap(true, false);
670 CHECK_NULL_VOID(pixelMap);
671 auto dragNodeCopy = CreateImageNode(pixelMap);
672 CHECK_NULL_VOID(dragNodeCopy);
673
674 //mount to gatherNode
675 gatherNode->AddChild(dragNodeCopy);
676 overlayManager->SetDragNodeCopy(dragNodeCopy);
677
678 //update position
679 int32_t width = pixelMap->GetWidth();
680 int32_t height = pixelMap->GetHeight();
681 auto offset = DragDropFuncWrapper::GetPaintRectCenter(frameNode) -
682 OffsetF(width / HALF_DIVIDE, height / HALF_DIVIDE);
683 DragDropFuncWrapper::UpdateNodePositionToWindow(dragNodeCopy, offset);
684 auto copyNodeRenderContext = dragNodeCopy->GetRenderContext();
685 CHECK_NULL_VOID(copyNodeRenderContext);
686 copyNodeRenderContext->UpdateTransformScale({ 1.0f, 1.0f });
687 }
688
ShowDragNodeCopyAnimation(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode)689 void DragAnimationHelper::ShowDragNodeCopyAnimation(const RefPtr<OverlayManager>& overlayManager,
690 const RefPtr<FrameNode>& frameNode)
691 {
692 CHECK_NULL_VOID(frameNode);
693 CHECK_NULL_VOID(overlayManager);
694 auto dragNodeCopy = overlayManager->GetDragNodeCopy();
695 CHECK_NULL_VOID(dragNodeCopy);
696 auto previewOptions = frameNode->GetDragPreviewOption();
697 if (!previewOptions.defaultAnimationBeforeLifting) {
698 return;
699 }
700 auto layoutProperty = frameNode->GetLayoutProperty();
701 if (layoutProperty) {
702 layoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
703 }
704 auto renderContext = dragNodeCopy->GetRenderContext();
705 AnimationOption option;
706 option.SetDuration(BEFORE_LIFTING_TIME);
707 auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(DEFAULT_INTERPOLATING_SPRING_VELOCITY,
708 DEFAULT_INTERPOLATING_SPRING_MASS, DEFAULT_INTERPOLATING_SPRING_STIFFNESS,
709 DEFAULT_INTERPOLATING_SPRING_DAMPING);
710 option.SetCurve(springCurve);
711 AnimationUtils::Animate(
712 option,
713 [renderContext]() mutable {
714 CHECK_NULL_VOID(renderContext);
715 renderContext->UpdateTransformScale({ DEFAULT_ANIMATION_SCALE, DEFAULT_ANIMATION_SCALE });
716 },
717 option.GetOnFinishEvent()
718 );
719 }
720
HideDragNodeCopyWithAnimation(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode)721 void DragAnimationHelper::HideDragNodeCopyWithAnimation(const RefPtr<OverlayManager>& overlayManager,
722 const RefPtr<FrameNode>& frameNode)
723 {
724 CHECK_NULL_VOID(frameNode);
725 CHECK_NULL_VOID(overlayManager);
726 auto dragNodeCopy = overlayManager->GetDragNodeCopy();
727 auto defaultAnimation = frameNode->GetDragPreviewOption().defaultAnimationBeforeLifting;
728 if (!dragNodeCopy) {
729 auto layoutProperty = frameNode->GetLayoutProperty();
730 if (layoutProperty && defaultAnimation) {
731 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
732 }
733 return;
734 }
735 auto renderContext = dragNodeCopy->GetRenderContext();
736 CHECK_NULL_VOID(renderContext);
737 AnimationOption option;
738 option.SetDuration(NODE_RESET_DURATION);
739 option.SetCurve(Curves::SHARP);
740 option.SetOnFinishEvent([renderContext, weak = AceType::WeakClaim(AceType::RawPtr(frameNode)),
741 defaultAnimation]() {
742 auto frameNode = weak.Upgrade();
743 if (frameNode) {
744 auto layoutProperty = frameNode->GetLayoutProperty();
745 if (layoutProperty && defaultAnimation) {
746 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
747 }
748 }
749 if (renderContext) {
750 renderContext->UpdateOpacity(0.0f);
751 }
752 });
753
754 AnimationUtils::Animate(
755 option,
756 [renderContext]() mutable {
757 CHECK_NULL_VOID(renderContext);
758 renderContext->UpdateTransformScale({ 1.0, 1.0f });
759 },
760 option.GetOnFinishEvent()
761 );
762 }
763
HideDragNodeCopy(const RefPtr<OverlayManager> & overlayManager)764 void DragAnimationHelper::HideDragNodeCopy(const RefPtr<OverlayManager>& overlayManager)
765 {
766 CHECK_NULL_VOID(overlayManager);
767 auto dragNodeCopy = overlayManager->GetDragNodeCopy();
768 CHECK_NULL_VOID(dragNodeCopy);
769 auto renderContext = dragNodeCopy->GetRenderContext();
770 CHECK_NULL_VOID(renderContext);
771 renderContext->UpdateOpacity(0.0f);
772 }
773
UpdateBadgeTextNodePosition(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & textNode,int32_t childSize,float previewScale,OffsetF previewOffset)774 void DragAnimationHelper::UpdateBadgeTextNodePosition(const RefPtr<FrameNode>& frameNode,
775 const RefPtr<FrameNode>& textNode, int32_t childSize, float previewScale, OffsetF previewOffset)
776 {
777 if (childSize <= 1) {
778 return;
779 }
780 CHECK_NULL_VOID(frameNode);
781 CHECK_NULL_VOID(textNode);
782 auto textRenderContext = textNode->GetRenderContext();
783 CHECK_NULL_VOID(textRenderContext);
784 auto pixelMap = frameNode->GetDragPixelMap();
785 CHECK_NULL_VOID(pixelMap);
786 auto width = pixelMap->GetWidth();
787 auto height = pixelMap->GetHeight();
788 auto offset = previewOffset.NonOffset()
789 ? DragDropFuncWrapper::GetFrameNodeOffsetToWindow(textNode, frameNode, width, height)
790 : previewOffset;
791 auto badgeLength = std::to_string(childSize).size();
792 double textOffsetX = offset.GetX() + width * (previewScale + 1) / 2 - BADGE_RELATIVE_OFFSET.ConvertToPx() -
793 (BADGE_RELATIVE_OFFSET.ConvertToPx() * badgeLength);
794 double textOffsetY = offset.GetY() - height * (previewScale - 1) / 2 - BADGE_RELATIVE_OFFSET.ConvertToPx();
795 textRenderContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
796 textRenderContext->UpdatePosition(OffsetT<Dimension>(Dimension(textOffsetX), Dimension(textOffsetY)));
797 }
798
CreateBadgeTextNode(int32_t childSize)799 RefPtr<FrameNode> DragAnimationHelper::CreateBadgeTextNode(int32_t childSize)
800 {
801 if (childSize <= 1) {
802 return nullptr;
803 }
804 auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
805 []() { return AceType::MakeRefPtr<TextPattern>(); });
806 CHECK_NULL_RETURN(textNode, nullptr);
807 auto badgeLength = std::to_string(childSize).size();
808 DragAnimationHelper::UpdateBadgeLayoutAndRenderContext(textNode, badgeLength, childSize);
809
810 textNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
811 textNode->MarkModifyDone();
812 textNode->SetLayoutDirtyMarked(true);
813 textNode->SetActive(true);
814 return textNode;
815 }
816
ShowPreviewBadgeAnimation(const RefPtr<GestureEventHub> & gestureHub,const RefPtr<OverlayManager> & manager)817 void DragAnimationHelper::ShowPreviewBadgeAnimation(
818 const RefPtr<GestureEventHub>& gestureHub, const RefPtr<OverlayManager>& manager)
819 {
820 CHECK_NULL_VOID(gestureHub);
821 auto frameNode = gestureHub->GetFrameNode();
822 CHECK_NULL_VOID(frameNode);
823 auto dragPreviewOptions = frameNode->GetDragPreviewOption();
824 auto badgeNumber = dragPreviewOptions.GetCustomerBadgeNumber();
825 int32_t childSize = badgeNumber.has_value() ? badgeNumber.value()
826 : static_cast<int32_t>(manager->GetGatherNodeChildrenInfo().size()) + 1;
827 auto textNode = DragAnimationHelper::CreateBadgeTextNode(childSize);
828 CHECK_NULL_VOID(textNode);
829 auto column = manager->GetPixelMapNode();
830 CHECK_NULL_VOID(column);
831 column->AddChild(textNode);
832
833 DragAnimationHelper::UpdateBadgeTextNodePosition(frameNode, textNode, childSize, PIXELMAP_DRAG_SCALE_MULTIPLE);
834 DragAnimationHelper::ShowBadgeAnimation(textNode);
835 }
836
837 // update ImageNode default attr before floating
SetImageNodeInitAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)838 void DragAnimationHelper::SetImageNodeInitAttr(const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode)
839 {
840 CHECK_NULL_VOID(imageNode);
841 CHECK_NULL_VOID(frameNode);
842 auto imageContext = imageNode->GetRenderContext();
843 CHECK_NULL_VOID(imageContext);
844 auto dragPreviewOption = frameNode->GetDragPreviewOption();
845
846 // update default scale
847 imageContext->UpdateTransformScale({ 1.0f, 1.0f });
848
849 // update shadow
850 auto shadow = Shadow::CreateShadow(ShadowStyle::None);
851 if (dragPreviewOption.options.shadow.has_value()) {
852 shadow = dragPreviewOption.options.shadow.value();
853 shadow.SetColor(Color(0x00000000));
854 }
855 imageContext->UpdateBackShadow(shadow);
856
857 // update radius
858 auto borderRadius = DragDropFuncWrapper::GetDragFrameNodeBorderRadius(frameNode);
859 imageContext->UpdateBorderRadius(borderRadius);
860
861 // update opacity
862 imageContext->UpdateOpacity(1.0f);
863 }
864
SetImageNodeFinishAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)865 void DragAnimationHelper::SetImageNodeFinishAttr(const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode)
866 {
867 CHECK_NULL_VOID(imageNode);
868 CHECK_NULL_VOID(frameNode);
869 auto imageContext = imageNode->GetRenderContext();
870 CHECK_NULL_VOID(imageContext);
871 auto dragPreviewOption = frameNode->GetDragPreviewOption();
872 if (dragPreviewOption.options.shadow.has_value() && !dragPreviewOption.options.shadow->GetIsFilled()) {
873 imageContext->UpdateBackShadow(dragPreviewOption.options.shadow.value());
874 }
875 }
876
PreLayout(const RefPtr<FrameNode> & imageNode)877 void DragAnimationHelper::PreLayout(const RefPtr<FrameNode>& imageNode)
878 {
879 CHECK_NULL_VOID(imageNode);
880 auto subwindowContext = imageNode->GetContext();
881 if (subwindowContext) {
882 subwindowContext->FlushSyncGeometryNodeTasks();
883 subwindowContext->PreLayout(subwindowContext->GetTimeFromExternalTimer(), 0);
884 }
885 }
886
SetNodeVisible(const RefPtr<FrameNode> & frameNode,bool visible)887 void DragAnimationHelper::SetNodeVisible(const RefPtr<FrameNode>& frameNode, bool visible)
888 {
889 CHECK_NULL_VOID(frameNode);
890 auto renderContext = frameNode->GetRenderContext();
891 CHECK_NULL_VOID(renderContext);
892 renderContext->SetVisible(visible);
893 }
894
DragStartAnimation(const Offset & newOffset,const RefPtr<OverlayManager> & overlayManager,const OffsetF & gatherNodeCenter,Point point,int32_t containerId)895 void DragAnimationHelper::DragStartAnimation(const Offset& newOffset, const RefPtr<OverlayManager>& overlayManager,
896 const OffsetF& gatherNodeCenter, Point point, int32_t containerId)
897 {
898 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
899 CHECK_NULL_VOID(pipelineContext);
900 auto dragDropManager = pipelineContext->GetDragDropManager();
901 CHECK_NULL_VOID(dragDropManager);
902 AnimationOption option;
903 constexpr int32_t animateDuration = 300;
904 option.SetCurve(DRAG_CONTROL_ANIMATION_CURVE);
905 option.SetDuration(animateDuration);
906 option.SetOnFinishEvent([weakManager = AceType::WeakClaim(AceType::RawPtr(dragDropManager)), containerId]() {
907 auto dragDropManager = weakManager.Upgrade();
908 dragDropManager->SetStartAnimation(true);
909 if (dragDropManager && !dragDropManager->IsPullMoveReceivedForCurrentDrag()) {
910 DragControllerFuncWrapper::TransDragWindowToDragFwk(containerId);
911 }
912 });
913 auto imageNode = dragDropManager->GetDragPreviewInfo().imageNode;
914 CHECK_NULL_VOID(imageNode);
915 auto renderContext = imageNode->GetRenderContext();
916 CHECK_NULL_VOID(renderContext);
917 AnimationUtils::Animate(
918 option,
919 [renderContext, info = dragDropManager->GetDragPreviewInfo(), newOffset, overlayManager,
920 dragDropManager, gatherNodeCenter]() {
921 CHECK_NULL_VOID(renderContext);
922 renderContext->UpdateTransformScale({ info.scale, info.scale });
923 renderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
924 GatherAnimationInfo gatherAnimationInfo = { info.scale, info.width, info.height,
925 gatherNodeCenter, renderContext->GetBorderRadius() };
926 dragDropManager->UpdateGatherNodeAttr(overlayManager, gatherAnimationInfo);
927 dragDropManager->UpdateTextNodePosition(info.textNode, newOffset);
928 },
929 option.GetOnFinishEvent());
930 }
931
CreatePreviewNode(const RefPtr<FrameNode> & frameNode,RefPtr<FrameNode> & imageNode,float dragPreviewScale,const PreparedInfoForDrag & data)932 void DragAnimationHelper::CreatePreviewNode(const RefPtr<FrameNode>& frameNode, RefPtr<FrameNode>& imageNode,
933 float dragPreviewScale, const PreparedInfoForDrag& data)
934 {
935 CHECK_NULL_VOID(frameNode);
936 auto pixelMap = frameNode->GetDragPixelMap();
937 CHECK_NULL_VOID(pixelMap);
938 auto center = DragDropFuncWrapper::GetPaintRectCenter(frameNode);
939 auto frameOffset = OffsetF(0, 0);
940 imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
941 []() { return AceType::MakeRefPtr<ImagePattern>(); });
942 CHECK_NULL_VOID(imageNode);
943 imageNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
944
945 auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
946 CHECK_NULL_VOID(renderProps);
947 renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
948 auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
949 props->UpdateAutoResize(false);
950 props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
951 auto targetSize = CalcSize(NG::CalcLength(pixelMap->GetWidth()), NG::CalcLength(pixelMap->GetHeight()));
952 props->UpdateUserDefinedIdealSize(targetSize);
953
954 auto imagePattern = imageNode->GetPattern<ImagePattern>();
955 CHECK_NULL_VOID(imagePattern);
956 imagePattern->SetSyncLoad(true);
957
958 if (frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || !data.isMenuShow) {
959 frameOffset =
960 OffsetF(center.GetX() - (pixelMap->GetWidth() / 2.0f), center.GetY() - (pixelMap->GetHeight() / 2.0f));
961 DragEventActuator::UpdatePreviewPositionAndScale(imageNode, frameOffset, dragPreviewScale);
962 UpdatePreview(frameNode, imageNode, imageNode);
963 }
964 if ((frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
965 frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) &&
966 data.isMenuShow) {
967 frameOffset = OffsetF(center.GetX() - (data.menuPreviewRect.Width() / 2.0f),
968 center.GetY() - (data.menuPreviewRect.Height() / 2.0f));
969 CHECK_NULL_VOID(data.relativeContainerNode);
970 auto relativeContainerRenderContext = data.relativeContainerNode->GetRenderContext();
971 CHECK_NULL_VOID(relativeContainerRenderContext);
972 relativeContainerRenderContext->UpdatePosition(
973 OffsetT<Dimension>(Dimension(frameOffset.GetX()), Dimension(frameOffset.GetY())));
974 data.relativeContainerNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
975 UpdatePreview(frameNode, imageNode, data.relativeContainerNode);
976 }
977 }
978
UpdatePreview(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & dragNode)979 void DragAnimationHelper::UpdatePreview(
980 const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode, const RefPtr<FrameNode>& dragNode)
981 {
982 CHECK_NULL_VOID(frameNode);
983 CHECK_NULL_VOID(imageNode);
984 CHECK_NULL_VOID(dragNode);
985 DragEventActuator::UpdatePreviewAttr(frameNode, imageNode);
986 }
987
MountPixelMap(const RefPtr<OverlayManager> & manager,const RefPtr<GestureEventHub> & gestureHub,const PreparedInfoForDrag & data,bool isDragPixelMap)988 void DragAnimationHelper::MountPixelMap(const RefPtr<OverlayManager>& manager,
989 const RefPtr<GestureEventHub>& gestureHub, const PreparedInfoForDrag& data, bool isDragPixelMap)
990 {
991 CHECK_NULL_VOID(manager);
992 CHECK_NULL_VOID(data.imageNode);
993 CHECK_NULL_VOID(gestureHub);
994 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
995 AceType::MakeRefPtr<LinearLayoutPattern>(true));
996 CHECK_NULL_VOID(columnNode);
997 if (data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
998 !data.isMenuShow) {
999 columnNode->AddChild(data.imageNode);
1000 if (data.textNode) {
1001 columnNode->AddChild(data.textNode);
1002 }
1003 }
1004 if ((data.imageNode->GetDragPreviewOption().sizeChangeEffect ==
1005 DraggingSizeChangeEffect::SIZE_TRANSITION ||
1006 data.imageNode->GetDragPreviewOption().sizeChangeEffect ==
1007 DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION)&& data.isMenuShow) {
1008 MountPixelMapSizeContentTransition(data, columnNode);
1009 }
1010 auto hub = columnNode->GetOrCreateGestureEventHub();
1011 CHECK_NULL_VOID(hub);
1012 hub->SetPixelMap(gestureHub->GetPixelMap());
1013 auto container = Container::Current();
1014 if (container && container->IsScenceBoardWindow()) {
1015 auto frameNode = gestureHub->GetFrameNode();
1016 CHECK_NULL_VOID(frameNode);
1017 auto windowScene = manager->FindWindowScene(frameNode);
1018 manager->MountPixelMapToWindowScene(columnNode, windowScene, isDragPixelMap);
1019 } else {
1020 manager->MountPixelMapToRootNode(columnNode, isDragPixelMap);
1021 }
1022 DragEventActuator::SetPreviewDefaultAnimateProperty(data.imageNode);
1023 columnNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
1024 columnNode->MarkModifyDone();
1025 columnNode->SetActive(true);
1026 auto renderContext = columnNode->GetRenderContext();
1027 if (renderContext) {
1028 renderContext->MarkUiFirstNode(false);
1029 renderContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
1030 }
1031 MarkDirtyNode(columnNode);
1032
1033 if (!isDragPixelMap) {
1034 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
1035 CHECK_NULL_VOID(pipeline);
1036 pipeline->FlushSyncGeometryNodeTasks();
1037 }
1038 }
1039
MountPixelMapSizeContentTransition(const PreparedInfoForDrag & data,const RefPtr<FrameNode> & columnNode)1040 void DragAnimationHelper::MountPixelMapSizeContentTransition(
1041 const PreparedInfoForDrag& data, const RefPtr<FrameNode>& columnNode)
1042 {
1043 CHECK_NULL_VOID(data.imageNode);
1044 CHECK_NULL_VOID(data.relativeContainerNode);
1045 CHECK_NULL_VOID(columnNode);
1046 auto stackFrameNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG,
1047 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<StackPattern>(); });
1048 auto stackLayoutProperty = stackFrameNode->GetLayoutProperty();
1049 CHECK_NULL_VOID(stackLayoutProperty);
1050 stackLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(data.menuPreviewRect.Width(), DimensionUnit::PX),
1051 CalcLength(data.menuPreviewRect.Height(), DimensionUnit::PX) });
1052 stackLayoutProperty->UpdateAlignRules(
1053 { { AlignDirection::TOP, { .anchor = "__container__", .vertical = VerticalAlign::TOP } },
1054 { AlignDirection::RIGHT, { .anchor = "__container__", .horizontal = HorizontalAlign::END } } });
1055 auto stackContext = stackFrameNode->GetContext();
1056 CHECK_NULL_VOID(stackContext);
1057 auto renderContext = stackFrameNode->GetRenderContext();
1058 CHECK_NULL_VOID(renderContext);
1059 renderContext->UpdateClipEdge(true);
1060 renderContext->UpdateBorderRadius(data.borderRadius);
1061 columnNode->AddChild(data.relativeContainerNode);
1062 data.relativeContainerNode->AddChild(stackFrameNode);
1063 stackFrameNode->AddChild(data.imageNode);
1064 auto dragPreviewLayoutProperty = data.imageNode->GetLayoutProperty();
1065 CHECK_NULL_VOID(dragPreviewLayoutProperty);
1066 dragPreviewLayoutProperty->UpdateUserDefinedIdealSize(
1067 { CalcLength(0.0, DimensionUnit::AUTO), CalcLength(0.0, DimensionUnit::AUTO) });
1068 dragPreviewLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
1069 CreateAndMountMenuPreviewNode(data, stackFrameNode);
1070 if (data.textNode) {
1071 auto textRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1072 AceType::MakeRefPtr<LinearLayoutPattern>(false));
1073 textRow->AddChild(data.textNode);
1074 auto textRowLayoutProperty = textRow->GetLayoutProperty();
1075 CHECK_NULL_VOID(textRowLayoutProperty);
1076 auto textRowRenderContext = textRow->GetRenderContext();
1077 CHECK_NULL_VOID(textRowRenderContext);
1078 textRowRenderContext->UpdateOffset(OffsetT<Dimension>(
1079 Dimension(BADGE_RELATIVE_OFFSET.ConvertToPx()), Dimension(-BADGE_RELATIVE_OFFSET.ConvertToPx())));
1080 textRowLayoutProperty->UpdateAlignRules(
1081 { { AlignDirection::TOP, { .anchor = "__container__", .vertical = VerticalAlign::TOP } },
1082 { AlignDirection::RIGHT, { .anchor = "__container__", .horizontal = HorizontalAlign::END } } });
1083
1084 data.relativeContainerNode->AddChild(textRow);
1085 }
1086 }
1087
CreateAndMountMenuPreviewNode(const PreparedInfoForDrag & data,const RefPtr<FrameNode> & stackFrameNode)1088 void DragAnimationHelper::CreateAndMountMenuPreviewNode(
1089 const PreparedInfoForDrag& data, const RefPtr<FrameNode>& stackFrameNode)
1090 {
1091 CHECK_NULL_VOID(data.imageNode);
1092 CHECK_NULL_VOID(data.menuPreviewNode);
1093 if (data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) {
1094 auto menuPreviewImageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
1095 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
1096 CHECK_NULL_VOID(menuPreviewImageNode);
1097 auto menuPreviewImageNodeLayoutProperty = menuPreviewImageNode->GetLayoutProperty<ImageLayoutProperty>();
1098 CHECK_NULL_VOID(menuPreviewImageNodeLayoutProperty);
1099 auto menuPreviewRenderContext = data.menuPreviewNode->GetRenderContext();
1100 CHECK_NULL_VOID(menuPreviewRenderContext);
1101 auto menuPreviewPixelMap = menuPreviewRenderContext->GetThumbnailPixelMap(true);
1102 menuPreviewImageNodeLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(menuPreviewPixelMap));
1103 auto menuPreviewImagePattern = menuPreviewImageNode->GetPattern<ImagePattern>();
1104 CHECK_NULL_VOID(menuPreviewImagePattern);
1105 menuPreviewImagePattern->SetSyncLoad(true);
1106 menuPreviewImageNodeLayoutProperty->UpdateUserDefinedIdealSize(
1107 { CalcLength(0.0, DimensionUnit::AUTO), CalcLength(0.0, DimensionUnit::AUTO) });
1108 menuPreviewImageNodeLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
1109 menuPreviewImageNodeLayoutProperty->UpdateImageFit(ImageFit::COVER);
1110 auto menuPreviewImageRenderContext = menuPreviewImageNode->GetRenderContext();
1111 CHECK_NULL_VOID(menuPreviewImageRenderContext);
1112 menuPreviewImageRenderContext->UpdateOpacity(1.0f);
1113 stackFrameNode->AddChild(menuPreviewImageNode);
1114 auto dragPreviewRenderContext = data.imageNode->GetRenderContext();
1115 CHECK_NULL_VOID(dragPreviewRenderContext);
1116 dragPreviewRenderContext->UpdateOpacity(0.0f);
1117 }
1118 }
1119 } // namespace OHOS::Ace::NG
1120