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