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/animation_util.h"
17
18 #include "bridge/common/dom/dom_node.h"
19 #include "bridge/common/utils/utils.h"
20
21 namespace OHOS::Ace {
22 namespace {
23
24 template<class T>
ParseFunctionValue(const std::string & line,const std::string & key,std::function<T (const std::string &)> parser)25 T ParseFunctionValue(const std::string& line, const std::string& key, std::function<T(const std::string&)> parser)
26 {
27 std::vector<std::string> strs;
28 StringUtils::SplitStr(line, " ", strs, true);
29 for (const auto& str : strs) {
30 if (str.empty()) {
31 continue;
32 }
33 auto leftIndex = str.find('(');
34 auto rightIndex = str.find(')');
35 if (leftIndex == std::string::npos || rightIndex == std::string::npos) {
36 continue;
37 }
38 if (leftIndex + 1 >= rightIndex) {
39 continue;
40 }
41 if (str.substr(0, leftIndex) != key) {
42 continue;
43 }
44
45 auto valueStr = str.substr(leftIndex + 1, rightIndex - leftIndex - 1);
46 return parser(valueStr);
47 }
48 return T {};
49 }
50
GetTransformTypeValue(const std::unique_ptr<JsonValue> & transformJson)51 std::string GetTransformTypeValue(const std::unique_ptr<JsonValue>& transformJson)
52 {
53 if (transformJson->IsNull()) {
54 LOGE("transformJson is null");
55 return "";
56 }
57 std::string jsonValue = transformJson->GetString();
58 if (jsonValue.empty()) {
59 double jsonDouble = transformJson->GetDouble();
60 return std::to_string(jsonDouble);
61 }
62 return jsonValue;
63 }
64
GetTransformType(const std::unique_ptr<JsonValue> & transformJson)65 std::string GetTransformType(const std::unique_ptr<JsonValue>& transformJson)
66 {
67 if (transformJson->IsNull()) {
68 LOGE("transformJson is null");
69 return "";
70 }
71 return transformJson->GetKey();
72 }
73
74 } // namespace
75
ParseAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes,const RefPtr<Declaration> & declaration,const RefPtr<ThemeConstants> themeConstants)76 void AnimationUtil::ParseAnimationStyle(
77 const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes,
78 const RefPtr<Declaration>& declaration, const RefPtr<ThemeConstants> themeConstants)
79 {
80 if (declaration) {
81 isRightToLeft = declaration->IsRightToLeft();
82 }
83 themeConstants_ = themeConstants;
84
85 Clear();
86
87 for (const auto& animationNameKeyframe : animationKeyframes) {
88 auto animationName = animationNameKeyframe.find(DOM_ANIMATION_NAME);
89 if (animationName != animationNameKeyframe.end()) {
90 animationName_ = animationName->second;
91 if (declaration) {
92 auto& animationStyle =
93 declaration->MaybeResetStyle<CommonAnimationStyle>(StyleTag::COMMON_ANIMATION_STYLE);
94 if (animationStyle.IsValid()) {
95 animationStyle.animationOperation = AnimationOperation::PLAY;
96 }
97 }
98 continue;
99 }
100
101 // time from keyframe; offset from js api
102 auto pos = animationNameKeyframe.find(DOM_ANIMATION_NAME_TIME);
103 if (pos == animationNameKeyframe.end()) {
104 pos = animationNameKeyframe.find(DOM_ANIMATION_OFFSET);
105 }
106 if (pos == animationNameKeyframe.end()) {
107 continue;
108 }
109 auto timeStr = pos->second;
110 if (timeStr.empty()) {
111 continue;
112 }
113
114 for (const auto& [keyStyle, value] : animationNameKeyframe) {
115 if (keyStyle == DOM_ANIMATION_NAME_TIME || keyStyle == DOM_ANIMATION_OFFSET) {
116 continue;
117 }
118 KeyframesAddKeyFrame(keyStyle, value, timeStr);
119 }
120 }
121 if (!shadowKeyframes_.empty()) {
122 for (auto&& [key, shadow] : shadowKeyframes_) {
123 double time = StringUtils::StringToDouble(key) / 100.0;
124 AddAnimatable(shadow, time, AnimatableType::PROPERTY_BOX_SHADOW);
125 }
126 }
127 }
128
KeyframesAddKeyFrame(const std::string & keyStyle,const std::string & value,const std::string & timeStr)129 void AnimationUtil::KeyframesAddKeyFrame(
130 const std::string& keyStyle, const std::string& value, const std::string& timeStr)
131 {
132 static const std::unordered_map<std::string,
133 void (*)(const std::string&, const double&, const std::string&, AnimationUtil&)>
134 keyFrameAddMap = {
135 { DOM_BACKGROUND_COLOR,
136 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
137 util.AddAnimatable(util.ParseColor(value), time, AnimatableType::PROPERTY_BG_COLOR);
138 } },
139 { DOM_BACKGROUND_IMAGE_SIZE,
140 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
141 BackgroundImageSize backgroundImageSize;
142 if (!Framework::ParseBackgroundImageSize(value, backgroundImageSize)) {
143 LOGW("ParseBackgroundImageSize failed.");
144 return;
145 }
146 util.AddAnimatable(backgroundImageSize, time, AnimatableType::PROPERTY_BACKGROUND_SIZE);
147 } },
148 { DOM_BACKGROUND_IMAGE_POSITION,
149 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
150 BackgroundImagePosition backgroundImagePosition;
151 if (!Framework::ParseBackgroundImagePosition(value, backgroundImagePosition)) {
152 LOGW("ParseBackgroundImagePosition failed.");
153 return;
154 }
155 util.AddAnimatable(backgroundImagePosition, time, AnimatableType::PROPERTY_BACKGROUND_POSITION);
156 } },
157 { DOM_WIDTH,
158 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
159 LOGE("DOM_WIDTH:%{public}s time:%{public}lf", value.c_str(), time);
160 util.AddAnimatable(util.ParseDimension(value), time, AnimatableType::PROPERTY_WIDTH);
161 } },
162 { DOM_HEIGHT,
163 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
164 util.AddAnimatable(util.ParseDimension(value), time, AnimatableType::PROPERTY_HEIGHT);
165 } },
166 { DOM_OPACITY,
167 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
168 util.AddAnimatable<float>(util.ParseDouble(value), time, AnimatableType::PROPERTY_OPACITY);
169 } },
170 // margin
171 { DOM_MARGIN_LEFT,
172 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
173 util.AddAnimatable(
174 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
175 } },
176 { DOM_MARGIN_RIGHT,
177 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
178 util.AddAnimatable(
179 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
180 } },
181 { DOM_MARGIN_TOP,
182 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
183 util.AddAnimatable(
184 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_TOP);
185 } },
186 { DOM_MARGIN_BOTTOM,
187 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
188 util.AddAnimatable(
189 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_BOTTOM);
190 } },
191 { DOM_MARGIN_START,
192 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
193 if (util.isRightToLeft) {
194 util.AddAnimatable(
195 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
196 } else {
197 util.AddAnimatable(
198 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
199 }
200 } },
201 { DOM_MARGIN_END,
202 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
203 if (util.isRightToLeft) {
204 util.AddAnimatable(
205 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
206 } else {
207 util.AddAnimatable(
208 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
209 }
210 } },
211 { DOM_MARGIN,
212 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
213 auto margin = util.ParseDimension(value);
214 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_LEFT);
215 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_TOP);
216 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_RIGHT);
217 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_BOTTOM);
218 } },
219 // padding
220 { DOM_PADDING_LEFT,
221 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
222 util.AddAnimatable(
223 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_LEFT);
224 } },
225 { DOM_PADDING_RIGHT,
226 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
227 util.AddAnimatable(
228 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_RIGHT);
229 } },
230 { DOM_PADDING_TOP,
231 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
232 util.AddAnimatable(
233 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_TOP);
234 } },
235 { DOM_PADDING_BOTTOM,
236 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
237 util.AddAnimatable(
238 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_BOTTOM);
239 } },
240 { DOM_PADDING_START,
241 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
242 auto padding = util.ParseDimension(value);
243 if (util.isRightToLeft) {
244 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
245 } else {
246 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
247 }
248 } },
249 { DOM_PADDING_END,
250 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
251 auto padding = util.ParseDimension(value);
252 if (util.isRightToLeft) {
253 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
254 } else {
255 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
256 }
257 } },
258 { DOM_PADDING,
259 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
260 auto padding = util.ParseDimension(value);
261 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
262 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_TOP);
263 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
264 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_BOTTOM);
265 } },
266 // border
267 { DOM_BORDER_LEFT_WIDTH,
268 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
269 util.AddAnimatable<float>(
270 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_LEFT_WIDTH);
271 } },
272 { DOM_BORDER_RIGHT_WIDTH,
273 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
274 util.AddAnimatable<float>(
275 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH);
276 } },
277 { DOM_BORDER_TOP_WIDTH,
278 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
279 util.AddAnimatable<float>(
280 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_TOP_WIDTH);
281 } },
282 { DOM_BORDER_BOTTOM_WIDTH,
283 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
284 util.AddAnimatable<float>(
285 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH);
286 } },
287 { DOM_BORDER_WIDTH,
288 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
289 auto borderWidth = util.ParseDouble(value);
290 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_LEFT_WIDTH);
291 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH);
292 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_TOP_WIDTH);
293 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH);
294 } },
295 { DOM_BORDER_RADIUS,
296 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
297 auto radius = util.ParseDouble(value);
298 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS);
299 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS);
300 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
301 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
302 } },
303 { DOM_BORDER_TOP_LEFT_RADIUS,
304 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
305 auto radius = util.ParseDouble(value);
306 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS);
307 } },
308 { DOM_BORDER_TOP_RIGHT_RADIUS,
309 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
310 auto radius = util.ParseDouble(value);
311 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS);
312 } },
313 { DOM_BORDER_BOTTOM_LEFT_RADIUS,
314 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
315 auto radius = util.ParseDouble(value);
316 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
317 } },
318 { DOM_BORDER_BOTTOM_RIGHT_RADIUS,
319 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
320 auto radius = util.ParseDouble(value);
321 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
322 } },
323 { DOM_BORDER_LEFT_COLOR,
324 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
325 auto color = util.ParseColor(value);
326 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_LEFT_COLOR);
327 } },
328 { DOM_BORDER_RIGHT_COLOR,
329 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
330 auto color = util.ParseColor(value);
331 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_RIGHT_COLOR);
332 } },
333 { DOM_BORDER_TOP_COLOR,
334 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
335 auto color = util.ParseColor(value);
336 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_TOP_COLOR);
337 } },
338 { DOM_BORDER_BOTTOM_COLOR,
339 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
340 auto color = util.ParseColor(value);
341 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR);
342 } },
343 { DOM_BORDER_COLOR,
344 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
345 auto color = util.ParseColor(value);
346 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_LEFT_COLOR);
347 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_TOP_COLOR);
348 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_RIGHT_COLOR);
349 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR);
350 } },
351 { DOM_BORDER_LEFT_STYLE,
352 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
353 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
354 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_LEFT_STYLE);
355 } },
356 { DOM_BORDER_RIGHT_STYLE,
357 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
358 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
359 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_RIGHT_STYLE);
360 } },
361 { DOM_BORDER_TOP_STYLE,
362 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
363 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
364 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_TOP_STYLE);
365 } },
366 { DOM_BORDER_BOTTOM_STYLE,
367 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
368 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
369 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE);
370 } },
371 { DOM_BORDER_STYLE,
372 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
373 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
374 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_LEFT_STYLE);
375 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_TOP_STYLE);
376 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_RIGHT_STYLE);
377 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE);
378 } },
379 { DOM_FILTER,
380 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
381 auto radius = ParseFunctionValue<Dimension>(value, DOM_BLUR, Framework::StringToDimension);
382 if (GreatOrEqual(radius.Value(), 0.0)) {
383 util.AddAnimatable<float>(
384 static_cast<float>(radius.Value()), time, AnimatableType::PROPERTY_FILTER_BLUR);
385 }
386 } },
387 { DOM_BACKDROP_FILTER,
388 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
389 auto radius = ParseFunctionValue<Dimension>(value, DOM_BLUR, Framework::StringToDimension);
390 if (GreatOrEqual(radius.Value(), 0.0)) {
391 util.AddAnimatable<float>(
392 static_cast<float>(radius.Value()), time, AnimatableType::PROPERTY_BACKDROP_FILTER_BLUR);
393 }
394 } },
395 { DOM_WINDOW_FILTER,
396 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
397 std::vector<std::string> offsets;
398 StringUtils::StringSplitter(value, ' ', offsets);
399 // property animation only support progress
400 if (!offsets.empty()) {
401 auto progress =
402 ParseFunctionValue<Dimension>(offsets[0], DOM_BLUR, Framework::StringToDimension);
403 if (progress.Unit() == DimensionUnit::PERCENT) {
404 if (GreatOrEqual(progress.Value(), 0.0) && LessOrEqual(progress.Value(), 1.0)) {
405 util.AddAnimatable<float>(static_cast<float>(progress.Value()), time,
406 AnimatableType::PROPERTY_WINDOW_FILTER_BLUR);
407 }
408 }
409 }
410 } },
411 // BoxShadow
412 { DOM_BOX_SHADOW_H,
413 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
414 auto& shadow = util.shadowKeyframes_[timeStr];
415 shadow.SetOffsetX(util.ParseDouble(value));
416 } },
417 { DOM_BOX_SHADOW_V,
418 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
419 auto& shadow = util.shadowKeyframes_[timeStr];
420 shadow.SetOffsetY(util.ParseDouble(value));
421 } },
422 { DOM_BOX_SHADOW_BLUR,
423 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
424 auto& shadow = util.shadowKeyframes_[timeStr];
425 shadow.SetBlurRadius(util.ParseDouble(value));
426 } },
427 { DOM_BOX_SHADOW_SPREAD,
428 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
429 auto& shadow = util.shadowKeyframes_[timeStr];
430 shadow.SetSpreadRadius(util.ParseDouble(value));
431 } },
432 { DOM_BOX_SHADOW_COLOR,
433 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
434 auto& shadow = util.shadowKeyframes_[timeStr];
435 shadow.SetColor(util.ParseColor(value));
436 } },
437 // position
438 { DOM_POSITION_LEFT,
439 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
440 util.AddAnimatable(
441 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_LEFT);
442 } },
443 { DOM_POSITION_TOP,
444 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
445 util.AddAnimatable(
446 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_TOP);
447 } },
448 { DOM_POSITION_RIGHT,
449 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
450 util.AddAnimatable(
451 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_RIGHT);
452 } },
453 { DOM_POSITION_BOTTOM,
454 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
455 util.AddAnimatable(
456 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_BOTTOM);
457 } },
458 { DOM_TRANSFORM,
459 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
460 std::unique_ptr<JsonValue> transformJson = JsonUtil::ParseJsonString(value);
461 if (transformJson->GetArraySize() == 0) {
462 // when empty should insert an identity matrix.
463 util.transformConvertor_.InsertIdentityKeyframe(time);
464 }
465 for (int32_t index = 0; index < transformJson->GetArraySize(); ++index) {
466 std::string typeKey = GetTransformType(transformJson->GetArrayItem(index));
467 std::string typeValue = GetTransformTypeValue(transformJson->GetArrayItem(index));
468 if ((!typeKey.empty()) && (!typeValue.empty())) {
469 util.transformConvertor_.Convert(typeKey, typeValue, time);
470 }
471 }
472 } },
473 };
474 auto pos = keyFrameAddMap.find(keyStyle);
475 if (pos != keyFrameAddMap.end()) {
476 double time = StringUtils::StringToDouble(timeStr) / 100.0;
477 pos->second(value, time, timeStr, *this);
478 }
479 }
480
CreateKeyboardAnimationOption(const KeyboardAnimationConfig & config,float keyboardHeight)481 AnimationOption AnimationUtil::CreateKeyboardAnimationOption(
482 const KeyboardAnimationConfig& config, float keyboardHeight)
483 {
484 static const LinearMapNode<RefPtr<Curve>> curveMap[] = {
485 { "ease", Curves::EASE },
486 { "easeIn", Curves::EASE_IN },
487 { "easeInOut", Curves::EASE_IN_OUT },
488 { "easeOut", Curves::EASE_OUT },
489 { "default", Curves::EASE_IN_OUT },
490 { "linear", Curves::LINEAR },
491 { "spring", AceType::MakeRefPtr<ResponsiveSpringMotion>(ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_RESPONSE,
492 ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_DAMPING_RATIO,
493 ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_BLEND_DURATION) },
494 { "interactiveSpring", AceType::MakeRefPtr<ResponsiveSpringMotion>(
495 ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE,
496 ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO,
497 ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION) },
498 };
499
500 AnimationOption option;
501 NearZero(keyboardHeight) ? option.SetDuration(config.durationOut_) : option.SetDuration(config.durationIn_);
502 RefPtr<Curve> curve;
503 if (config.curveType_ == "cubic" && config.curveParams_.size() == 4) {
504 // cubic curve needs 4 params
505 curve = AceType::MakeRefPtr<CubicCurve>(
506 config.curveParams_[0], config.curveParams_[1], config.curveParams_[2], config.curveParams_[3]);
507 } else if (config.curveType_ == "interpolatingSpring" && config.curveParams_.size() == 4) {
508 // interpolatingSpring needs 4 params
509 curve = AceType::MakeRefPtr<InterpolatingSpring>(
510 config.curveParams_[0], config.curveParams_[1], config.curveParams_[2], config.curveParams_[3]);
511 } else {
512 auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), config.curveType_.c_str());
513 curve = index < 0 ? nullptr : curveMap[index].value;
514 }
515 option.SetCurve(curve);
516 return option;
517 }
518
519 template<class T>
AddAnimatable(const T & value,double time,AnimatableType type)520 void AnimationUtil::AddAnimatable(const T& value, double time, AnimatableType type)
521 {
522 auto animatable = AceType::MakeRefPtr<AnimatableData<T>>(value);
523 animatable->SetTimePoint(time);
524 if (propAnimationMap_.find(type) == propAnimationMap_.end()) {
525 propAnimationMap_[type] = AceType::MakeRefPtr<PropertyAnimation>(type);
526 }
527 propAnimationMap_[type]->AddAnimatable(animatable);
528 }
529
GetThemeConstants() const530 RefPtr<ThemeConstants> AnimationUtil::GetThemeConstants() const
531 {
532 return themeConstants_;
533 }
534
ParseColor(const std::string & value,uint32_t maskAlpha) const535 Color AnimationUtil::ParseColor(const std::string& value, uint32_t maskAlpha) const
536 {
537 auto&& noRefFunc = [&value, maskAlpha = maskAlpha]() { return Color::FromString(value, maskAlpha); };
538 auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetColor(refId); };
539 if (!themeConstants_) {
540 noRefFunc();
541 }
542 return ParseThemeReference<Color>(value, noRefFunc, idRefFunc, Color::TRANSPARENT);
543 }
544
ParseDouble(const std::string & value) const545 double AnimationUtil::ParseDouble(const std::string& value) const
546 {
547 auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
548 auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetDouble(refId); };
549 if (!themeConstants_) {
550 noRefFunc();
551 }
552 return ParseThemeReference<double>(value, noRefFunc, idRefFunc, 0.0);
553 }
554
ParseDimension(const std::string & value) const555 Dimension AnimationUtil::ParseDimension(const std::string& value) const
556 {
557 auto&& noRefFunc = [&value]() { return StringUtils::StringToDimension(value); };
558 auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetDimension(refId); };
559 if (!themeConstants_) {
560 noRefFunc();
561 }
562 return ParseThemeReference<Dimension>(value, noRefFunc, idRefFunc, Dimension());
563 }
564
565 } // namespace OHOS::Ace
566