• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_value ret = nullptr;
224             napi_value valueNapi = nullptr;
225             napi_value onframe = nullptr;
226             auto result = napi_get_reference_value(env, onframeRef, &onframe);
227             if (result != napi_ok || onframe == nullptr) {
228                 LOGW("get onframe in callback failed");
229                 return;
230             }
231             napi_create_double(env, value, &valueNapi);
232             napi_call_function(env, nullptr, onframe, 1, &valueNapi, &ret);
233         });
234         animator->AddInterpolator(animation);
235     }
236     napi_value result;
237     napi_get_null(env, &result);
238     return result;
239 }
240 
241 // since API 9 deprecated
JSUpdate(napi_env env,napi_callback_info info)242 static napi_value JSUpdate(napi_env env, napi_callback_info info)
243 {
244     LOGI("JsAnimator: JSUpdate");
245     return JSReset(env, info);
246 }
247 
JSPlay(napi_env env,napi_callback_info info)248 static napi_value JSPlay(napi_env env, napi_callback_info info)
249 {
250     LOGI("JsAnimator: JSPlay");
251     auto animator = GetAnimatorInResult(env, info);
252     if (!animator) {
253         LOGE("animator is null");
254         return nullptr;
255     }
256     if (!animator->HasScheduler()) {
257         animator->AttachSchedulerOnContainer();
258     }
259     animator->Play();
260     napi_value result = nullptr;
261     napi_get_null(env, &result);
262     return result;
263 }
264 
JSFinish(napi_env env,napi_callback_info info)265 static napi_value JSFinish(napi_env env, napi_callback_info info)
266 {
267     LOGI("JsAnimator: JSFinish");
268     auto animator = GetAnimatorInResult(env, info);
269     if (!animator) {
270         LOGE("animator is null");
271         return nullptr;
272     }
273     animator->Finish();
274     napi_value result = nullptr;
275     napi_get_null(env, &result);
276     return result;
277 }
278 
JSPause(napi_env env,napi_callback_info info)279 static napi_value JSPause(napi_env env, napi_callback_info info)
280 {
281     LOGI("JsAnimator: JSPause");
282     auto animator = GetAnimatorInResult(env, info);
283     if (!animator) {
284         LOGE("animator is null");
285         return nullptr;
286     }
287     animator->Pause();
288     napi_value result;
289     napi_get_null(env, &result);
290     return result;
291 }
292 
JSCancel(napi_env env,napi_callback_info info)293 static napi_value JSCancel(napi_env env, napi_callback_info info)
294 {
295     LOGI("JsAnimator: JSCancel");
296     auto animator = GetAnimatorInResult(env, info);
297     if (!animator) {
298         LOGE("animator is null");
299         return nullptr;
300     }
301     animator->Cancel();
302     napi_value result;
303     napi_get_null(env, &result);
304     return result;
305 }
306 
JSReverse(napi_env env,napi_callback_info info)307 static napi_value JSReverse(napi_env env, napi_callback_info info)
308 {
309     LOGI("JsAnimator: JSReverse");
310     auto animator = GetAnimatorInResult(env, info);
311     if (!animator) {
312         LOGE("animator is null");
313         return nullptr;
314     }
315     if (!animator->HasScheduler()) {
316         animator->AttachSchedulerOnContainer();
317     }
318     animator->Reverse();
319     napi_value result;
320     napi_get_null(env, &result);
321     return result;
322 }
323 
SetOnframe(napi_env env,napi_callback_info info)324 static napi_value SetOnframe(napi_env env, napi_callback_info info)
325 {
326     LOGI("JsAnimator: SetOnframe");
327     AnimatorResult* animatorResult = nullptr;
328     size_t argc = 1;
329     napi_value thisVar = nullptr;
330     napi_value onframe = nullptr;
331     napi_get_cb_info(env, info, &argc, &onframe, &thisVar, NULL);
332     napi_unwrap(env, thisVar, (void**)&animatorResult);
333     if (!animatorResult) {
334         LOGE("unwrap animator result is failed");
335         return nullptr;
336     }
337     auto option = animatorResult->GetAnimatorOption();
338     if (!option) {
339         LOGE("option is null");
340         return nullptr;
341     }
342     auto animator = animatorResult->GetAnimator();
343     if (!animator) {
344         LOGE("animator is null");
345         return nullptr;
346     }
347     animator->ClearInterpolators();
348     auto curve = Framework::CreateCurve(option->easing);
349     auto animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, curve);
350     // convert onframe function to reference
351     napi_ref onframeRef = animatorResult->GetOnframeRef();
352     if (onframeRef) {
353         uint32_t count = 0;
354         napi_reference_unref(env, onframeRef, &count);
355     }
356     napi_create_reference(env, onframe, 1, &onframeRef);
357     animatorResult->SetOnframeRef(onframeRef);
358     animation->AddListener([env, onframeRef](double value) {
359         napi_value ret = nullptr;
360         napi_value valueNapi = nullptr;
361         napi_value onframe = nullptr;
362         auto result = napi_get_reference_value(env, onframeRef, &onframe);
363         if (result != napi_ok || onframe == nullptr) {
364             LOGW("get onframe in callback failed");
365             return;
366         }
367         napi_create_double(env, value, &valueNapi);
368         napi_call_function(env, nullptr, onframe, 1, &valueNapi, &ret);
369     });
370     animator->AddInterpolator(animation);
371     if (!animator->HasScheduler()) {
372         animator->AttachSchedulerOnContainer();
373     }
374     napi_value undefined;
375     napi_get_undefined(env, &undefined);
376     return undefined;
377 }
378 
SetOnfinish(napi_env env,napi_callback_info info)379 static napi_value SetOnfinish(napi_env env, napi_callback_info info)
380 {
381     LOGI("JsAnimator: SetOnfinish");
382     AnimatorResult* animatorResult = nullptr;
383     size_t argc = 1;
384     napi_value thisVar = nullptr;
385     napi_value onfinish = nullptr;
386     napi_get_cb_info(env, info, &argc, &onfinish, &thisVar, NULL);
387     napi_unwrap(env, thisVar, (void**)&animatorResult);
388     if (!animatorResult) {
389         LOGE("unwrap animator result is failed");
390         return nullptr;
391     }
392     auto option = animatorResult->GetAnimatorOption();
393     if (!option) {
394         LOGE("option is null");
395         return nullptr;
396     }
397     auto animator = animatorResult->GetAnimator();
398     if (!animator) {
399         LOGE("animator is null");
400         return nullptr;
401     }
402     // convert onfinish function to reference
403     napi_ref onfinishRef = animatorResult->GetOnfinishRef();
404     if (onfinishRef) {
405         uint32_t count = 0;
406         napi_reference_unref(env, onfinishRef, &count);
407     }
408     napi_create_reference(env, onfinish, 1, &onfinishRef);
409     animatorResult->SetOnfinishRef(onfinishRef);
410     animator->ClearStopListeners();
411     animator->AddStopListener([env, onfinishRef] {
412         LOGI("JsAnimator: onfinish->AddIdleListener");
413         napi_value ret = nullptr;
414         napi_value onfinish = nullptr;
415         auto result = napi_get_reference_value(env, onfinishRef, &onfinish);
416         if (result != napi_ok || onfinish == nullptr) {
417             LOGW("get onfinish in callback failed");
418             return;
419         }
420         napi_call_function(env, NULL, onfinish, 0, NULL, &ret);
421     });
422     napi_value undefined;
423     napi_get_undefined(env, &undefined);
424     return undefined;
425 }
426 
SetOncancel(napi_env env,napi_callback_info info)427 static napi_value SetOncancel(napi_env env, napi_callback_info info)
428 {
429     LOGI("JsAnimator: SetOncancel");
430     AnimatorResult* animatorResult = nullptr;
431     size_t argc = 1;
432     napi_value thisVar = nullptr;
433     napi_value oncancel = nullptr;
434     napi_get_cb_info(env, info, &argc, &oncancel, &thisVar, NULL);
435     napi_unwrap(env, thisVar, (void**)&animatorResult);
436     if (!animatorResult) {
437         LOGE("unwrap animator result is failed");
438         return nullptr;
439     }
440     auto option = animatorResult->GetAnimatorOption();
441     if (!option) {
442         LOGE("option is null");
443         return nullptr;
444     }
445     auto animator = animatorResult->GetAnimator();
446     if (!animator) {
447         LOGE("animator is null");
448         return nullptr;
449     }
450     // convert oncancel function to reference
451     napi_ref oncancelRef = animatorResult->GetOncancelRef();
452     if (oncancelRef) {
453         uint32_t count = 0;
454         napi_reference_unref(env, oncancelRef, &count);
455     }
456     napi_create_reference(env, oncancel, 1, &oncancelRef);
457     animatorResult->SetOncancelRef(oncancelRef);
458     animator->ClearIdleListeners();
459     animator->AddIdleListener([env, oncancelRef] {
460         LOGI("JsAnimator: oncancel->AddIdleListener");
461         napi_value ret = nullptr;
462         napi_value oncancel = nullptr;
463         auto result = napi_get_reference_value(env, oncancelRef, &oncancel);
464         if (result != napi_ok || oncancel == nullptr) {
465             LOGW("get oncancel in callback failed");
466             return;
467         }
468         napi_call_function(env, NULL, oncancel, 0, NULL, &ret);
469     });
470     napi_value undefined;
471     napi_get_undefined(env, &undefined);
472     return undefined;
473 }
474 
SetOnrepeat(napi_env env,napi_callback_info info)475 static napi_value SetOnrepeat(napi_env env, napi_callback_info info)
476 {
477     LOGI("JsAnimator: SetOnrepeat");
478     AnimatorResult* animatorResult = nullptr;
479     size_t argc = 1;
480     napi_value thisVar = nullptr;
481     napi_value onrepeat = nullptr;
482     napi_get_cb_info(env, info, &argc, &onrepeat, &thisVar, NULL);
483     napi_unwrap(env, thisVar, (void**)&animatorResult);
484     if (!animatorResult) {
485         LOGE("unwrap animator result is failed");
486         return nullptr;
487     }
488     auto option = animatorResult->GetAnimatorOption();
489     if (!option) {
490         LOGE("option is null");
491         return nullptr;
492     }
493     auto animator = animatorResult->GetAnimator();
494     if (!animator) {
495         LOGE("animator is null");
496         return nullptr;
497     }
498     // convert onrepeat function to reference
499     napi_ref onrepeatRef = animatorResult->GetOnrepeatRef();
500     if (onrepeatRef) {
501         uint32_t count = 0;
502         napi_reference_unref(env, onrepeatRef, &count);
503     }
504     napi_create_reference(env, onrepeat, 1, &onrepeatRef);
505     animatorResult->SetOnrepeatRef(onrepeatRef);
506     animator->ClearRepeatListeners();
507     animator->AddRepeatListener([env, onrepeatRef] {
508         LOGI("JsAnimator: onrepeat->AddIdleListener");
509         napi_value ret = nullptr;
510         napi_value onrepeat = nullptr;
511         auto result = napi_get_reference_value(env, onrepeatRef, &onrepeat);
512         if (result != napi_ok || onrepeat == nullptr) {
513             LOGW("get onrepeat in callback failed");
514             return;
515         }
516         napi_call_function(env, NULL, onrepeat, 0, NULL, &ret);
517     });
518     napi_value undefined;
519     napi_get_undefined(env, &undefined);
520     return undefined;
521 }
522 
JSCreate(napi_env env,napi_callback_info info)523 static napi_value JSCreate(napi_env env, napi_callback_info info)
524 {
525     LOGI("JsAnimator: JSCreate");
526     auto option = std::make_shared<AnimatorOption>();
527     ParseAnimatorOption(env, info, option);
528     auto animator = AceType::MakeRefPtr<Animator>();
529     animator->AttachSchedulerOnContainer();
530     AnimatorResult* animatorResult = new AnimatorResult(animator, option);
531     napi_value jsAnimator = nullptr;
532     napi_create_object(env, &jsAnimator);
533     napi_wrap(
534         env, jsAnimator, animatorResult,
535         [](napi_env env, void* data, void* hint) {
536             AnimatorResult* animatorResult = (AnimatorResult*)data;
537             // release four references(onFunc) before releasing animatorResult
538             napi_ref onframeRef = animatorResult->GetOnframeRef();
539             napi_ref onfinishRef = animatorResult->GetOnfinishRef();
540             napi_ref oncancelRef = animatorResult->GetOncancelRef();
541             napi_ref onrepeatRef = animatorResult->GetOnrepeatRef();
542             if (onframeRef != nullptr) {
543                 napi_delete_reference(env, onframeRef);
544             }
545             if (onfinishRef != nullptr) {
546                 napi_delete_reference(env, onfinishRef);
547             }
548             if (oncancelRef != nullptr) {
549                 napi_delete_reference(env, oncancelRef);
550             }
551             if (onrepeatRef != nullptr) {
552                 napi_delete_reference(env, onrepeatRef);
553             }
554             delete animatorResult;
555         },
556         nullptr, nullptr);
557     napi_property_descriptor resultFuncs[] = {
558         DECLARE_NAPI_FUNCTION("update", JSUpdate),
559         DECLARE_NAPI_FUNCTION("reset", JSReset),
560         DECLARE_NAPI_FUNCTION("play", JSPlay),
561         DECLARE_NAPI_FUNCTION("finish", JSFinish),
562         DECLARE_NAPI_FUNCTION("pause", JSPause),
563         DECLARE_NAPI_FUNCTION("cancel", JSCancel),
564         DECLARE_NAPI_FUNCTION("reverse", JSReverse),
565         DECLARE_NAPI_SETTER("onframe", SetOnframe),
566         DECLARE_NAPI_SETTER("onfinish", SetOnfinish),
567         DECLARE_NAPI_SETTER("oncancel", SetOncancel),
568         DECLARE_NAPI_SETTER("onrepeat", SetOnrepeat),
569     };
570 
571     NAPI_CALL(env, napi_define_properties(env, jsAnimator, sizeof(resultFuncs) / sizeof(resultFuncs[0]), resultFuncs));
572     return jsAnimator;
573 }
574 
575 // since API 9 deprecated
JSCreateAnimator(napi_env env,napi_callback_info info)576 static napi_value JSCreateAnimator(napi_env env, napi_callback_info info)
577 {
578     LOGI("JsAnimator: JSCreateAnimator");
579     return JSCreate(env, info);
580 }
581 
AnimatorExport(napi_env env,napi_value exports)582 static napi_value AnimatorExport(napi_env env, napi_value exports)
583 {
584     LOGI("JsAnimator: AnimatorExport");
585     napi_property_descriptor animatorDesc[] = {
586         DECLARE_NAPI_FUNCTION("create", JSCreate),
587         DECLARE_NAPI_FUNCTION("createAnimator", JSCreateAnimator),
588     };
589     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(animatorDesc) / sizeof(animatorDesc[0]), animatorDesc));
590     return exports;
591 }
592 
593 static napi_module animatorModule = {
594     .nm_version = 1,
595     .nm_flags = 0,
596     .nm_filename = nullptr,
597     .nm_register_func = AnimatorExport,
598     .nm_modname = "animator",
599     .nm_priv = ((void*)0),
600     .reserved = { 0 },
601 };
602 
AnimatorRegister()603 extern "C" __attribute__((constructor)) void AnimatorRegister()
604 {
605     napi_module_register(&animatorModule);
606 }
607 
ApplyOption()608 void AnimatorResult::ApplyOption()
609 {
610     CHECK_NULL_VOID_NOLOG(animator_);
611     CHECK_NULL_VOID_NOLOG(option_);
612     animator_->SetDuration(option_->duration);
613     animator_->SetIteration(option_->iterations);
614     animator_->SetStartDelay(option_->delay);
615     animator_->SetFillMode(StringToFillMode(option_->fill));
616     animator_->SetAnimationDirection(StringToAnimationDirection(option_->direction));
617 }
618 
619 } // namespace OHOS::Ace::Napi
620