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