1 /*
2 * Copyright (c) 2021-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 "click_spring_effect.h"
17 #include "render_transform.h"
18
19 #include <unordered_map>
20
21 namespace OHOS::Ace {
22 namespace {
23
24 struct SpringEffectProperty {
25 double scale_;
26 double velocity_;
27 RefPtr<SpringProperty> springProperty_;
28 };
29
30 const static std::unordered_map<ClickSpringEffectType, SpringEffectProperty> CLICK_SPRING_EFFECT_PROPERTIES = {
31 { ClickSpringEffectType::SMALL, { 0.9, 1, AceType::MakeRefPtr<SpringProperty>(0.5, 410.0, 38.0) } },
32 { ClickSpringEffectType::MEDIUM, { 0.95, 0.5, AceType::MakeRefPtr<SpringProperty>(0.5, 350.0, 35.0) } },
33 { ClickSpringEffectType::LARGE, { 0.95, 0, AceType::MakeRefPtr<SpringProperty>(0.5, 240.0, 28.0) } },
34 };
35
36 } // namespace
37
ClickSpringEffect(const WeakPtr<PipelineContext> & context)38 ClickSpringEffect::ClickSpringEffect(const WeakPtr<PipelineContext>& context)
39 {
40 controller_ = CREATE_ANIMATOR(context);
41 }
42
FinishPreviousAnimation()43 void ClickSpringEffect::FinishPreviousAnimation()
44 {
45 if (controller_ && !controller_->IsStopped()) {
46 controller_->Finish();
47 }
48 }
49
ShowAnimation(TouchType touchType,ClickSpringEffectType type)50 void ClickSpringEffect::ShowAnimation(TouchType touchType, ClickSpringEffectType type)
51 {
52 FinishPreviousAnimation();
53 auto propertyPos = CLICK_SPRING_EFFECT_PROPERTIES.find(type);
54 if (propertyPos == CLICK_SPRING_EFFECT_PROPERTIES.end()) {
55 LOGE("can't find type %{public}d", type);
56 return;
57 }
58
59 auto& effectProperty = propertyPos->second;
60 RefPtr<SpringMotion> springMotion;
61 switch (touchType) {
62 case TouchType::DOWN:
63 springMotion = AceType::MakeRefPtr<SpringMotion>(
64 GetScale(), effectProperty.scale_, effectProperty.velocity_, effectProperty.springProperty_);
65 break;
66 case TouchType::UP:
67 case TouchType::CANCEL:
68 springMotion = AceType::MakeRefPtr<SpringMotion>(
69 GetScale(), 1.0, effectProperty.velocity_, effectProperty.springProperty_);
70 break;
71 default:
72 return;
73 }
74 if (!springMotion) {
75 return;
76 }
77
78 springMotion->AddListener([weakEffect = AceType::WeakClaim(this)](double value) {
79 auto effect = weakEffect.Upgrade();
80 if (effect) {
81 effect->SetScale(value);
82 effect->MarkRender();
83 }
84 });
85
86 if (controller_) {
87 controller_->PlayMotion(springMotion);
88 }
89 }
90
MarkRender()91 void ClickSpringEffect::MarkRender()
92 {
93 auto node = renderNode_.Upgrade();
94 if (node == nullptr) {
95 return;
96 }
97
98 node->MarkNeedLayout();
99 auto transform = AceType::DynamicCast<RenderTransform>(node);
100 if (transform == nullptr) {
101 return;
102 }
103 transform->SetPendingUpdateTransformLayer();
104 }
105
106 } // namespace OHOS::Ace
107