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