1 /*
2 * Copyright (c) 2021 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/animation/property_animation.h"
17
18 #include "core/animation/animatable_data.h"
19 #include "core/components/box/render_box.h"
20
21 namespace OHOS::Ace {
22
PropertyAnimation(AnimatableType type)23 PropertyAnimation::PropertyAnimation(AnimatableType type)
24 {
25 type_ = type;
26 }
27
SetStart(const RefPtr<Animatable> & animatable)28 void PropertyAnimation::SetStart(const RefPtr<Animatable>& animatable)
29 {
30 if (animatable == nullptr) {
31 return;
32 }
33 animatable->SetTimePoint(0.0f);
34 animatables_.emplace_front(animatable);
35 }
36
AddAnimatable(const RefPtr<Animatable> & animatable)37 void PropertyAnimation::AddAnimatable(const RefPtr<Animatable>& animatable)
38 {
39 if (animatable == nullptr) {
40 return;
41 }
42 animatables_.emplace_back(animatable);
43 }
44
SetCurve(const RefPtr<Curve> & curve)45 void PropertyAnimation::SetCurve(const RefPtr<Curve>& curve)
46 {
47 if (!curve) {
48 LOGE("set curve failed. curve is null.");
49 return;
50 }
51 for (auto& animatable : animatables_) {
52 animatable->SetCurve(curve);
53 }
54 }
55
OnNormalizedTimestampChanged(float normalized,bool reverse)56 void PropertyAnimation::OnNormalizedTimestampChanged(float normalized, bool reverse)
57 {
58 if (normalized < NORMALIZED_DURATION_MIN || normalized > NORMALIZED_DURATION_MAX) {
59 LOGE("normalized time check failed. normalized: %{public}f", normalized);
60 return;
61 }
62 Calculate(normalized);
63 }
64
OnInitNotify(float normalizedTime,bool reverse)65 void PropertyAnimation::OnInitNotify(float normalizedTime, bool reverse)
66 {
67 if (init_ && animateTo_) {
68 animateTo_(init_);
69 } else {
70 OnNormalizedTimestampChanged(normalizedTime, reverse);
71 }
72 }
73
GetCurve()74 RefPtr<Curve> PropertyAnimation::GetCurve()
75 {
76 if (!animatables_.empty() && animatables_.front()->GetCurve() != nullptr) {
77 return animatables_.front()->GetCurve();
78 }
79 return Curves::EASE_IN_OUT;
80 }
81
Calculate(float keyTime)82 void PropertyAnimation::Calculate(float keyTime)
83 {
84 if (animatables_.empty()) {
85 return;
86 }
87 auto preAnimatable = animatables_.front();
88 for (const auto& animatable : animatables_) {
89 if (keyTime < animatable->GetTimePoint()) {
90 float preKeyTime = preAnimatable->GetTimePoint();
91 float innerKeyTime = (keyTime - preKeyTime) / (animatable->GetTimePoint() - preKeyTime);
92 TriggerFrame(preAnimatable, animatable, innerKeyTime);
93 return;
94 }
95 preAnimatable = animatable;
96 }
97 // in range [1.0, inf]
98 const auto& lastAnimatable = animatables_.back();
99 TriggerFrame(lastAnimatable, lastAnimatable, 1.0);
100 }
101
TriggerFrame(const RefPtr<Animatable> & start,const RefPtr<Animatable> & end,float time)102 void PropertyAnimation::TriggerFrame(const RefPtr<Animatable>& start, const RefPtr<Animatable>& end, float time)
103 {
104 if (animateTo_ == nullptr) {
105 return;
106 }
107 switch (type_) {
108 case AnimatableType::PROPERTY_WIDTH:
109 case AnimatableType::PROPERTY_HEIGHT:
110 case AnimatableType::PROPERTY_MARGIN_LEFT:
111 case AnimatableType::PROPERTY_MARGIN_TOP:
112 case AnimatableType::PROPERTY_MARGIN_RIGHT:
113 case AnimatableType::PROPERTY_MARGIN_BOTTOM:
114 case AnimatableType::PROPERTY_PADDING_LEFT:
115 case AnimatableType::PROPERTY_PADDING_TOP:
116 case AnimatableType::PROPERTY_PADDING_RIGHT:
117 case AnimatableType::PROPERTY_PADDING_BOTTOM:
118 case AnimatableType::PROPERTY_POSITION_LEFT:
119 case AnimatableType::PROPERTY_POSITION_TOP:
120 case AnimatableType::PROPERTY_POSITION_RIGHT:
121 case AnimatableType::PROPERTY_POSITION_BOTTOM: {
122 Next<Dimension>(start, end, time);
123 break;
124 }
125 case AnimatableType::PROPERTY_BG_COLOR:
126 case AnimatableType::PROPERTY_BORDER_LEFT_COLOR:
127 case AnimatableType::PROPERTY_BORDER_TOP_COLOR:
128 case AnimatableType::PROPERTY_BORDER_RIGHT_COLOR:
129 case AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR: {
130 Next<Color>(start, end, time);
131 break;
132 }
133 case AnimatableType::PROPERTY_OPACITY:
134 case AnimatableType::PROPERTY_BACKDROP_FILTER_BLUR:
135 case AnimatableType::PROPERTY_FILTER_BLUR:
136 case AnimatableType::PROPERTY_WINDOW_FILTER_BLUR:
137 case AnimatableType::PROPERTY_BORDER_LEFT_WIDTH:
138 case AnimatableType::PROPERTY_BORDER_TOP_WIDTH:
139 case AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH:
140 case AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH:
141 case AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS:
142 case AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS:
143 case AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS:
144 case AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS: {
145 Next<float>(start, end, time);
146 break;
147 }
148 case AnimatableType::PROPERTY_BACKGROUND_SIZE: {
149 Next<BackgroundImageSize>(start, end, time);
150 break;
151 }
152 case AnimatableType::PROPERTY_BACKGROUND_POSITION: {
153 Next<BackgroundImagePosition>(start, end, time);
154 break;
155 }
156 case AnimatableType::PROPERTY_BOX_SHADOW: {
157 Next<Shadow>(start, end, time);
158 break;
159 }
160 case AnimatableType::PROPERTY_BORDER_LEFT_STYLE:
161 case AnimatableType::PROPERTY_BORDER_TOP_STYLE:
162 case AnimatableType::PROPERTY_BORDER_RIGHT_STYLE:
163 case AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE: {
164 Next<BorderStyle>(start, end, time);
165 break;
166 }
167 default:
168 break;
169 }
170 }
171
172 template<class T>
Next(const RefPtr<Animatable> & start,const RefPtr<Animatable> & end,float time)173 void PropertyAnimation::Next(const RefPtr<Animatable>& start, const RefPtr<Animatable>& end, float time)
174 {
175 auto from = AceType::DynamicCast<AnimatableData<T>>(start);
176 auto to = AceType::DynamicCast<AnimatableData<T>>(end);
177 auto value = AceType::MakeRefPtr<AnimatableData<T>>(T {});
178 if (from != nullptr && to != nullptr && value != nullptr) {
179 float process = to->GetCurve()->Move(time);
180 value->SetValue(to->Animate(from->GetValue(), to->GetValue(), process));
181 animateTo_(value);
182 }
183 }
184
185 } // namespace OHOS::Ace
186