1 /*
2 * Copyright (c) 2022-2023 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 <memory>
17 #include <string>
18
19 #include "animator_option.h"
20 #include "interfaces/napi/kits/utils/napi_utils.h"
21 #include "napi/native_api.h"
22 #include "napi/native_engine/native_value.h"
23 #include "napi/native_node_api.h"
24
25 #include "base/log/log.h"
26 #include "base/memory/ace_type.h"
27 #include "base/memory/referenced.h"
28 #include "bridge/common/utils/utils.h"
29 #include "core/animation/animator.h"
30 #include "core/animation/curve.h"
31 #include "core/animation/curve_animation.h"
32
33 namespace OHOS::Ace::Napi {
34
ParseString(napi_env env,napi_value propertyNapi,std::string & property)35 static void ParseString(napi_env env, napi_value propertyNapi, std::string& property)
36 {
37 if (propertyNapi != nullptr) {
38 napi_valuetype valueType = napi_undefined;
39 napi_typeof(env, propertyNapi, &valueType);
40 if (valueType == napi_undefined) {
41 NapiThrow(env, "Required input parameters are missing.", Framework::ERROR_CODE_PARAM_INVALID);
42 return;
43 } else if (valueType != napi_string) {
44 NapiThrow(env, "The type of parameters is incorrect.", Framework::ERROR_CODE_PARAM_INVALID);
45 return;
46 }
47 auto nativeProperty = reinterpret_cast<NativeValue*>(propertyNapi);
48 auto resultProperty = nativeProperty->ToString();
49 auto nativeStringProperty =
50 reinterpret_cast<NativeString*>(resultProperty->GetInterface(NativeString::INTERFACE_ID));
51 size_t propertyLen = nativeStringProperty->GetLength() + 1;
52 std::unique_ptr<char[]> propertyString = std::make_unique<char[]>(propertyLen);
53 size_t retLen = 0;
54 napi_get_value_string_utf8(env, propertyNapi, propertyString.get(), propertyLen, &retLen);
55 property = propertyString.get();
56 }
57 }
58
ParseInt(napi_env env,napi_value propertyNapi,int32_t & property)59 static void ParseInt(napi_env env, napi_value propertyNapi, int32_t& property)
60 {
61 if (propertyNapi != nullptr) {
62 napi_valuetype valueType = napi_undefined;
63 napi_typeof(env, propertyNapi, &valueType);
64 if (valueType == napi_undefined) {
65 NapiThrow(env, "Required input parameters are missing.", Framework::ERROR_CODE_PARAM_INVALID);
66 return;
67 } else if (valueType != napi_number) {
68 NapiThrow(env, "The type of parameters is incorrect.", Framework::ERROR_CODE_PARAM_INVALID);
69 return;
70 }
71 napi_get_value_int32(env, propertyNapi, &property);
72 }
73 }
74
ParseDouble(napi_env env,napi_value propertyNapi,double & property)75 static void ParseDouble(napi_env env, napi_value propertyNapi, double& property)
76 {
77 if (propertyNapi != nullptr) {
78 napi_valuetype valueType = napi_undefined;
79 napi_typeof(env, propertyNapi, &valueType);
80 if (valueType == napi_undefined) {
81 NapiThrow(env, "Required input parameters are missing.", Framework::ERROR_CODE_PARAM_INVALID);
82 return;
83 } else if (valueType != napi_number) {
84 NapiThrow(env, "The type of parameters is incorrect.", Framework::ERROR_CODE_PARAM_INVALID);
85 return;
86 }
87 napi_get_value_double(env, propertyNapi, &property);
88 }
89 }
90
StringToFillMode(const std::string & fillMode)91 static FillMode StringToFillMode(const std::string& fillMode)
92 {
93 if (fillMode.compare("forwards") == 0) {
94 return FillMode::FORWARDS;
95 } else if (fillMode.compare("backwards") == 0) {
96 return FillMode::BACKWARDS;
97 } else if (fillMode.compare("both") == 0) {
98 return FillMode::BOTH;
99 } else {
100 return FillMode::NONE;
101 }
102 }
103
StringToAnimationDirection(const std::string & direction)104 static AnimationDirection StringToAnimationDirection(const std::string& direction)
105 {
106 if (direction.compare("alternate") == 0) {
107 return AnimationDirection::ALTERNATE;
108 } else if (direction.compare("reverse") == 0) {
109 return AnimationDirection::REVERSE;
110 } else if (direction.compare("alternate-reverse") == 0) {
111 return AnimationDirection::ALTERNATE_REVERSE;
112 } else {
113 return AnimationDirection::NORMAL;
114 }
115 }
116
ParseAnimatorOption(napi_env env,napi_callback_info info,std::shared_ptr<AnimatorOption> & option)117 static void ParseAnimatorOption(napi_env env, napi_callback_info info, std::shared_ptr<AnimatorOption>& option)
118 {
119 LOGI("JsAnimator: ParseAnimatorOption");
120 size_t argc = 1;
121 napi_value argv;
122 napi_get_cb_info(env, info, &argc, &argv, NULL, NULL);
123 if (argc != 1) {
124 NapiThrow(env, "The number of parameters must be equal to 1.", Framework::ERROR_CODE_PARAM_INVALID);
125 return;
126 }
127 napi_value durationNapi = nullptr;
128 napi_value easingNapi = nullptr;
129 napi_value delayNapi = nullptr;
130 napi_value fillNapi = nullptr;
131 napi_value directionNapi = nullptr;
132 napi_value iterationsNapi = nullptr;
133 napi_value beginNapi = nullptr;
134 napi_value endNapi = nullptr;
135 napi_valuetype valueType = napi_undefined;
136 napi_typeof(env, argv, &valueType);
137 if (valueType == napi_object) {
138 napi_get_named_property(env, argv, "duration", &durationNapi);
139 napi_get_named_property(env, argv, "easing", &easingNapi);
140 napi_get_named_property(env, argv, "delay", &delayNapi);
141 napi_get_named_property(env, argv, "fill", &fillNapi);
142 napi_get_named_property(env, argv, "direction", &directionNapi);
143 napi_get_named_property(env, argv, "iterations", &iterationsNapi);
144 napi_get_named_property(env, argv, "begin", &beginNapi);
145 napi_get_named_property(env, argv, "end", &endNapi);
146 } else {
147 NapiThrow(env, "The type of parameters is incorrect.", Framework::ERROR_CODE_PARAM_INVALID);
148 return;
149 }
150
151 int32_t duration = 0;
152 int32_t delay = 0;
153 int32_t iterations = 0;
154 double begin = 0.0;
155 double end = 0.0;
156 std::string easing = "ease";
157 std::string fill = "none";
158 std::string direction = "normal";
159 ParseString(env, easingNapi, easing);
160 ParseString(env, fillNapi, fill);
161 ParseString(env, directionNapi, direction);
162 ParseInt(env, durationNapi, duration);
163 ParseInt(env, delayNapi, delay);
164 ParseInt(env, iterationsNapi, iterations);
165 ParseDouble(env, beginNapi, begin);
166 ParseDouble(env, endNapi, end);
167 option->duration = duration;
168 option->delay = delay;
169 option->iterations = iterations;
170 option->begin = begin;
171 option->end = end;
172 option->easing = easing;
173 option->fill = fill;
174 option->direction = direction;
175 }
176
GetAnimatorInResult(napi_env env,napi_callback_info info)177 static RefPtr<Animator> GetAnimatorInResult(napi_env env, napi_callback_info info)
178 {
179 AnimatorResult* animatorResult = nullptr;
180 napi_value thisVar;
181 napi_get_cb_info(env, info, NULL, NULL, &thisVar, NULL);
182 napi_unwrap(env, thisVar, (void**)&animatorResult);
183 if (!animatorResult) {
184 LOGE("unwrap animator result is failed");
185 return nullptr;
186 }
187 return animatorResult->GetAnimator();
188 }
189
JSReset(napi_env env,napi_callback_info info)190 static napi_value JSReset(napi_env env, napi_callback_info info)
191 {
192 LOGI("JsAnimator: JSReset");
193 AnimatorResult* animatorResult = nullptr;
194 napi_value thisVar;
195 napi_get_cb_info(env, info, NULL, NULL, &thisVar, NULL);
196 napi_unwrap(env, thisVar, (void**)&animatorResult);
197 if (!animatorResult) {
198 LOGE("unwrap animator result is failed");
199 NapiThrow(env, "Internal error. Unwrap animator result is failed.", Framework::ERROR_CODE_INTERNAL_ERROR);
200 return nullptr;
201 }
202 auto option = animatorResult->GetAnimatorOption();
203 if (!option) {
204 LOGE("Option is null in AnimatorResult");
205 NapiThrow(env, "Internal error. Option is null in AnimatorResult.", Framework::ERROR_CODE_INTERNAL_ERROR);
206 return nullptr;
207 }
208 ParseAnimatorOption(env, info, option);
209 auto animator = animatorResult->GetAnimator();
210 if (!animator) {
211 LOGW("animator is null");
212 NapiThrow(env, "Internal error. Animator is null in AnimatorResult.", Framework::ERROR_CODE_INTERNAL_ERROR);
213 return nullptr;
214 }
215 animator->ClearInterpolators();
216 animator->ResetIsReverse();
217 animatorResult->ApplyOption();
218 napi_ref onframeRef = animatorResult->GetOnframeRef();
219 if (onframeRef) {
220 auto curve = Framework::CreateCurve(option->easing);
221 auto animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, curve);
222 animation->AddListener([env, onframeRef](double value) {
223 napi_handle_scope scope = nullptr;
224 napi_open_handle_scope(env, &scope);
225 if (scope == nullptr) {
226 LOGW("JsAnimator: open handle scope failed");
227 return;
228 }
229 napi_value ret = nullptr;
230 napi_value valueNapi = nullptr;
231 napi_value onframe = nullptr;
232 auto result = napi_get_reference_value(env, onframeRef, &onframe);
233 if (result != napi_ok || onframe == nullptr) {
234 LOGW("JsAnimator: get onframe in callback failed");
235 napi_close_handle_scope(env, scope);
236 return;
237 }
238 napi_create_double(env, value, &valueNapi);
239 napi_call_function(env, nullptr, onframe, 1, &valueNapi, &ret);
240 napi_close_handle_scope(env, scope);
241 });
242 animator->AddInterpolator(animation);
243 }
244 napi_value result;
245 napi_get_null(env, &result);
246 return result;
247 }
248
249 // since API 9 deprecated
JSUpdate(napi_env env,napi_callback_info info)250 static napi_value JSUpdate(napi_env env, napi_callback_info info)
251 {
252 LOGI("JsAnimator: JSUpdate");
253 return JSReset(env, info);
254 }
255
JSPlay(napi_env env,napi_callback_info info)256 static napi_value JSPlay(napi_env env, napi_callback_info info)
257 {
258 auto animator = GetAnimatorInResult(env, info);
259 LOGI("JsAnimator: JSPlay, id:%{public}d", animator ? animator->GetId() : -1);
260 if (!animator) {
261 LOGE("animator is null");
262 return nullptr;
263 }
264 if (!animator->HasScheduler()) {
265 animator->AttachSchedulerOnContainer();
266 }
267 animator->Play();
268 napi_value result = nullptr;
269 napi_get_null(env, &result);
270 return result;
271 }
272
JSFinish(napi_env env,napi_callback_info info)273 static napi_value JSFinish(napi_env env, napi_callback_info info)
274 {
275 auto animator = GetAnimatorInResult(env, info);
276 LOGI("JsAnimator: JSFinish, id:%{public}d", animator ? animator->GetId() : -1);
277 if (!animator) {
278 LOGE("animator is null");
279 return nullptr;
280 }
281 animator->Finish();
282 napi_value result = nullptr;
283 napi_get_null(env, &result);
284 return result;
285 }
286
JSPause(napi_env env,napi_callback_info info)287 static napi_value JSPause(napi_env env, napi_callback_info info)
288 {
289 auto animator = GetAnimatorInResult(env, info);
290 LOGI("JsAnimator: JSPause, id:%{public}d", animator ? animator->GetId() : -1);
291 if (!animator) {
292 LOGE("animator is null");
293 return nullptr;
294 }
295 animator->Pause();
296 napi_value result;
297 napi_get_null(env, &result);
298 return result;
299 }
300
JSCancel(napi_env env,napi_callback_info info)301 static napi_value JSCancel(napi_env env, napi_callback_info info)
302 {
303 auto animator = GetAnimatorInResult(env, info);
304 LOGI("JsAnimator: JSCancel, id:%{public}d", animator ? animator->GetId() : -1);
305 if (!animator) {
306 LOGE("animator is null");
307 return nullptr;
308 }
309 animator->Cancel();
310 napi_value result;
311 napi_get_null(env, &result);
312 return result;
313 }
314
JSReverse(napi_env env,napi_callback_info info)315 static napi_value JSReverse(napi_env env, napi_callback_info info)
316 {
317 auto animator = GetAnimatorInResult(env, info);
318 LOGI("JsAnimator: JSReverse, id:%{public}d", animator ? animator->GetId() : -1);
319 if (!animator) {
320 LOGE("animator is null");
321 return nullptr;
322 }
323 if (!animator->HasScheduler()) {
324 animator->AttachSchedulerOnContainer();
325 }
326 animator->Reverse();
327 napi_value result;
328 napi_get_null(env, &result);
329 return result;
330 }
331
SetOnframe(napi_env env,napi_callback_info info)332 static napi_value SetOnframe(napi_env env, napi_callback_info info)
333 {
334 LOGI("JsAnimator: SetOnframe");
335 AnimatorResult* animatorResult = nullptr;
336 size_t argc = 1;
337 napi_value thisVar = nullptr;
338 napi_value onframe = nullptr;
339 napi_get_cb_info(env, info, &argc, &onframe, &thisVar, NULL);
340 napi_unwrap(env, thisVar, (void**)&animatorResult);
341 if (!animatorResult) {
342 LOGE("unwrap animator result is failed");
343 return nullptr;
344 }
345 auto option = animatorResult->GetAnimatorOption();
346 if (!option) {
347 LOGE("option is null");
348 return nullptr;
349 }
350 auto animator = animatorResult->GetAnimator();
351 if (!animator) {
352 LOGE("animator is null");
353 return nullptr;
354 }
355 animator->ClearInterpolators();
356 auto curve = Framework::CreateCurve(option->easing);
357 auto animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, curve);
358 // convert onframe function to reference
359 napi_ref onframeRef = animatorResult->GetOnframeRef();
360 if (onframeRef) {
361 uint32_t count = 0;
362 napi_reference_unref(env, onframeRef, &count);
363 }
364 napi_create_reference(env, onframe, 1, &onframeRef);
365 animatorResult->SetOnframeRef(onframeRef);
366 animation->AddListener([env, onframeRef](double value) {
367 napi_handle_scope scope = nullptr;
368 napi_open_handle_scope(env, &scope);
369 if (scope == nullptr) {
370 LOGW("JsAnimator: open handle scope failed");
371 return;
372 }
373 napi_value ret = nullptr;
374 napi_value valueNapi = nullptr;
375 napi_value onframe = nullptr;
376 auto result = napi_get_reference_value(env, onframeRef, &onframe);
377 if (result != napi_ok || onframe == nullptr) {
378 LOGW("JsAnimator: get onframe in callback failed");
379 napi_close_handle_scope(env, scope);
380 return;
381 }
382 napi_create_double(env, value, &valueNapi);
383 napi_call_function(env, nullptr, onframe, 1, &valueNapi, &ret);
384 napi_close_handle_scope(env, scope);
385 });
386 animator->AddInterpolator(animation);
387 if (!animator->HasScheduler()) {
388 animator->AttachSchedulerOnContainer();
389 }
390 napi_value undefined;
391 napi_get_undefined(env, &undefined);
392 return undefined;
393 }
394
SetOnfinish(napi_env env,napi_callback_info info)395 static napi_value SetOnfinish(napi_env env, napi_callback_info info)
396 {
397 LOGI("JsAnimator: SetOnfinish");
398 AnimatorResult* animatorResult = nullptr;
399 size_t argc = 1;
400 napi_value thisVar = nullptr;
401 napi_value onfinish = nullptr;
402 napi_get_cb_info(env, info, &argc, &onfinish, &thisVar, NULL);
403 napi_unwrap(env, thisVar, (void**)&animatorResult);
404 if (!animatorResult) {
405 LOGE("unwrap animator result is failed");
406 return nullptr;
407 }
408 auto option = animatorResult->GetAnimatorOption();
409 if (!option) {
410 LOGE("option is null");
411 return nullptr;
412 }
413 auto animator = animatorResult->GetAnimator();
414 if (!animator) {
415 LOGE("animator is null");
416 return nullptr;
417 }
418 // convert onfinish function to reference
419 napi_ref onfinishRef = animatorResult->GetOnfinishRef();
420 if (onfinishRef) {
421 uint32_t count = 0;
422 napi_reference_unref(env, onfinishRef, &count);
423 }
424 napi_create_reference(env, onfinish, 1, &onfinishRef);
425 animatorResult->SetOnfinishRef(onfinishRef);
426 animator->ClearStopListeners();
427 animator->AddStopListener([env, onfinishRef] {
428 LOGI("JsAnimator: onfinish");
429 napi_handle_scope scope = nullptr;
430 napi_open_handle_scope(env, &scope);
431 if (scope == nullptr) {
432 LOGW("JsAnimator: open handle scope failed");
433 return;
434 }
435 napi_value ret = nullptr;
436 napi_value onfinish = nullptr;
437 auto result = napi_get_reference_value(env, onfinishRef, &onfinish);
438 if (result != napi_ok || onfinish == nullptr) {
439 LOGW("JsAnimator: get onfinish in callback failed");
440 napi_close_handle_scope(env, scope);
441 return;
442 }
443 napi_call_function(env, NULL, onfinish, 0, NULL, &ret);
444 napi_close_handle_scope(env, scope);
445 });
446 napi_value undefined;
447 napi_get_undefined(env, &undefined);
448 return undefined;
449 }
450
SetOncancel(napi_env env,napi_callback_info info)451 static napi_value SetOncancel(napi_env env, napi_callback_info info)
452 {
453 LOGI("JsAnimator: SetOncancel");
454 AnimatorResult* animatorResult = nullptr;
455 size_t argc = 1;
456 napi_value thisVar = nullptr;
457 napi_value oncancel = nullptr;
458 napi_get_cb_info(env, info, &argc, &oncancel, &thisVar, NULL);
459 napi_unwrap(env, thisVar, (void**)&animatorResult);
460 if (!animatorResult) {
461 LOGE("unwrap animator result is failed");
462 return nullptr;
463 }
464 auto option = animatorResult->GetAnimatorOption();
465 if (!option) {
466 LOGE("option is null");
467 return nullptr;
468 }
469 auto animator = animatorResult->GetAnimator();
470 if (!animator) {
471 LOGE("animator is null");
472 return nullptr;
473 }
474 // convert oncancel function to reference
475 napi_ref oncancelRef = animatorResult->GetOncancelRef();
476 if (oncancelRef) {
477 uint32_t count = 0;
478 napi_reference_unref(env, oncancelRef, &count);
479 }
480 napi_create_reference(env, oncancel, 1, &oncancelRef);
481 animatorResult->SetOncancelRef(oncancelRef);
482 animator->ClearIdleListeners();
483 animator->AddIdleListener([env, oncancelRef] {
484 LOGI("JsAnimator: oncancel");
485 napi_handle_scope scope = nullptr;
486 napi_open_handle_scope(env, &scope);
487 if (scope == nullptr) {
488 LOGW("JsAnimator: open handle scope failed");
489 return;
490 }
491 napi_value ret = nullptr;
492 napi_value oncancel = nullptr;
493 auto result = napi_get_reference_value(env, oncancelRef, &oncancel);
494 if (result != napi_ok || oncancel == nullptr) {
495 LOGW("JsAnimator: get oncancel in callback failed");
496 napi_close_handle_scope(env, scope);
497 return;
498 }
499 napi_call_function(env, NULL, oncancel, 0, NULL, &ret);
500 napi_close_handle_scope(env, scope);
501 });
502 napi_value undefined;
503 napi_get_undefined(env, &undefined);
504 return undefined;
505 }
506
SetOnrepeat(napi_env env,napi_callback_info info)507 static napi_value SetOnrepeat(napi_env env, napi_callback_info info)
508 {
509 LOGI("JsAnimator: SetOnrepeat");
510 AnimatorResult* animatorResult = nullptr;
511 size_t argc = 1;
512 napi_value thisVar = nullptr;
513 napi_value onrepeat = nullptr;
514 napi_get_cb_info(env, info, &argc, &onrepeat, &thisVar, NULL);
515 napi_unwrap(env, thisVar, (void**)&animatorResult);
516 if (!animatorResult) {
517 LOGE("unwrap animator result is failed");
518 return nullptr;
519 }
520 auto option = animatorResult->GetAnimatorOption();
521 if (!option) {
522 LOGE("option is null");
523 return nullptr;
524 }
525 auto animator = animatorResult->GetAnimator();
526 if (!animator) {
527 LOGE("animator is null");
528 return nullptr;
529 }
530 // convert onrepeat function to reference
531 napi_ref onrepeatRef = animatorResult->GetOnrepeatRef();
532 if (onrepeatRef) {
533 uint32_t count = 0;
534 napi_reference_unref(env, onrepeatRef, &count);
535 }
536 napi_create_reference(env, onrepeat, 1, &onrepeatRef);
537 animatorResult->SetOnrepeatRef(onrepeatRef);
538 animator->ClearRepeatListeners();
539 animator->AddRepeatListener([env, onrepeatRef] {
540 LOGI("JsAnimator: onrepeat");
541 napi_handle_scope scope = nullptr;
542 napi_open_handle_scope(env, &scope);
543 if (scope == nullptr) {
544 LOGW("JsAnimator: open handle scope failed");
545 return;
546 }
547 napi_value ret = nullptr;
548 napi_value onrepeat = nullptr;
549 auto result = napi_get_reference_value(env, onrepeatRef, &onrepeat);
550 if (result != napi_ok || onrepeat == nullptr) {
551 LOGW("JsAnimator: get onrepeat in callback failed");
552 napi_close_handle_scope(env, scope);
553 return;
554 }
555 napi_call_function(env, NULL, onrepeat, 0, NULL, &ret);
556 napi_close_handle_scope(env, scope);
557 });
558 napi_value undefined;
559 napi_get_undefined(env, &undefined);
560 return undefined;
561 }
562
JSCreate(napi_env env,napi_callback_info info)563 static napi_value JSCreate(napi_env env, napi_callback_info info)
564 {
565 LOGI("JsAnimator: JSCreate");
566 auto option = std::make_shared<AnimatorOption>();
567 ParseAnimatorOption(env, info, option);
568 auto animator = CREATE_ANIMATOR();
569 animator->AttachSchedulerOnContainer();
570 AnimatorResult* animatorResult = new AnimatorResult(animator, option);
571 napi_value jsAnimator = nullptr;
572 napi_create_object(env, &jsAnimator);
573 napi_wrap(
574 env, jsAnimator, animatorResult,
575 [](napi_env env, void* data, void* hint) {
576 AnimatorResult* animatorResult = (AnimatorResult*)data;
577 // release four references(onFunc) before releasing animatorResult
578 animatorResult->Destroy(env);
579 delete animatorResult;
580 },
581 nullptr, nullptr);
582 napi_property_descriptor resultFuncs[] = {
583 DECLARE_NAPI_FUNCTION("update", JSUpdate),
584 DECLARE_NAPI_FUNCTION("reset", JSReset),
585 DECLARE_NAPI_FUNCTION("play", JSPlay),
586 DECLARE_NAPI_FUNCTION("finish", JSFinish),
587 DECLARE_NAPI_FUNCTION("pause", JSPause),
588 DECLARE_NAPI_FUNCTION("cancel", JSCancel),
589 DECLARE_NAPI_FUNCTION("reverse", JSReverse),
590 DECLARE_NAPI_SETTER("onframe", SetOnframe),
591 DECLARE_NAPI_SETTER("onfinish", SetOnfinish),
592 DECLARE_NAPI_SETTER("oncancel", SetOncancel),
593 DECLARE_NAPI_SETTER("onrepeat", SetOnrepeat),
594 };
595
596 NAPI_CALL(env, napi_define_properties(env, jsAnimator, sizeof(resultFuncs) / sizeof(resultFuncs[0]), resultFuncs));
597 return jsAnimator;
598 }
599
600 // since API 9 deprecated
JSCreateAnimator(napi_env env,napi_callback_info info)601 static napi_value JSCreateAnimator(napi_env env, napi_callback_info info)
602 {
603 LOGI("JsAnimator: JSCreateAnimator");
604 return JSCreate(env, info);
605 }
606
AnimatorExport(napi_env env,napi_value exports)607 static napi_value AnimatorExport(napi_env env, napi_value exports)
608 {
609 LOGI("JsAnimator: AnimatorExport");
610 napi_property_descriptor animatorDesc[] = {
611 DECLARE_NAPI_FUNCTION("create", JSCreate),
612 DECLARE_NAPI_FUNCTION("createAnimator", JSCreateAnimator),
613 };
614 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(animatorDesc) / sizeof(animatorDesc[0]), animatorDesc));
615 return exports;
616 }
617
618 static napi_module animatorModule = {
619 .nm_version = 1,
620 .nm_flags = 0,
621 .nm_filename = nullptr,
622 .nm_register_func = AnimatorExport,
623 .nm_modname = "animator",
624 .nm_priv = ((void*)0),
625 .reserved = { 0 },
626 };
627
AnimatorRegister()628 extern "C" __attribute__((constructor)) void AnimatorRegister()
629 {
630 napi_module_register(&animatorModule);
631 }
632
ApplyOption()633 void AnimatorResult::ApplyOption()
634 {
635 CHECK_NULL_VOID_NOLOG(animator_);
636 CHECK_NULL_VOID_NOLOG(option_);
637 animator_->SetDuration(option_->duration);
638 animator_->SetIteration(option_->iterations);
639 animator_->SetStartDelay(option_->delay);
640 animator_->SetFillMode(StringToFillMode(option_->fill));
641 animator_->SetAnimationDirection(StringToAnimationDirection(option_->direction));
642 }
643
Destroy(napi_env env)644 void AnimatorResult::Destroy(napi_env env)
645 {
646 if (animator_) {
647 LOGI("JsAnimator: animator object start destroying, isStopped:%{public}d, id:%{public}d",
648 animator_->IsStopped(), animator_->GetId());
649 if (!animator_->IsStopped()) {
650 animator_->Stop();
651 LOGW("JsAnimator: animator force stopping done, id:%{public}d", animator_->GetId());
652 }
653 }
654 if (onframe_ != nullptr) {
655 napi_delete_reference(env, onframe_);
656 }
657 if (onfinish_ != nullptr) {
658 napi_delete_reference(env, onfinish_);
659 }
660 if (oncancel_ != nullptr) {
661 napi_delete_reference(env, oncancel_);
662 }
663 if (onrepeat_ != nullptr) {
664 napi_delete_reference(env, onrepeat_);
665 }
666 }
667
668 } // namespace OHOS::Ace::Napi
669