news 2026/4/18 7:56:31

鸿蒙原生系列之动画效果(关键帧动画)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙原生系列之动画效果(关键帧动画)

鸿蒙原生系列之关键帧动画

  • 〇、前言
  • 一、动画分类
    • 3、关键帧动画
      • 3.1、ArkUI_KeyframeAnimateOption
      • 3.2、动画时间与播放次数
      • 3.3、注册动画分段回调
      • 3.4、注册动画结束回调
      • 3.5、播放关键帧动画
  • 二、动画实现
    • 3、关键帧动画
      • 3.1、自定义按钮形状
      • 3.2、实现页面结构
      • 3.3、实现关键帧动画
      • 3.4、真机演示

〇、前言

上一篇,已经系统性学习了转场动画这种动画效果,接下来,继续学习另一种动画效果:关键帧动画

关键帧动画的代码,总体上,与最早学习的动画效果——属性动画,更为解决,都是需要用到专门的 API 接口——ArkUI_NativeAnimateAPI_1指针,而在转场动画的实现代码中,就完全不需要这个特殊API,反而像设置组件的尺寸那样写即可。

一、动画分类

3、关键帧动画

3.1、ArkUI_KeyframeAnimateOption

与属性动画的实现流程一样,关键帧动画也是需要先准备好动画参数对象,而在关键帧动画这边,这个关键的动画参对象,就是ArkUI_KeyframeAnimateOption。这个 ArkUI_KeyframeAnimateOption 对象的原型,SDK中尚未披露,所以 ,暂时无法深入了解它的结构。

ArkUI_KeyframeAnimateOption 对象实例,需要使用OH_ArkUI_KeyframeAnimateOption_Create方法创建,而该方法接受一个int32_t类型的参数,并且参数值与关键帧动画段数密切相关。

3.2、动画时间与播放次数

有了 ArkUI_KeyframeAnimateOption 实例后,就可以借助它去完成关键帧动画的持续时间和播放次数的设置。

设置关键帧动画持续时间,需要使用方法OH_ArkUI_KeyframeAnimateOption_SetDuration(ArkUI_KeyframeAnimateOption* option, int32_t value, int32_t index),参数 value 传入用于设置具体的持续时间,而 index 则指明此次设置作用在哪段关键帧动画上。

关键帧动画播放次数,用方法OH_ArkUI_KeyframeAnimateOption_SetIterations(ArkUI_KeyframeAnimateOption* option, int32_t value)进行设置,播放次数无需分段设置,直接作用在所有关键帧动画段上。

3.3、注册动画分段回调

此前就说过了,动画也是一种事件,动画是支持设置回调函数的。在关键帧动画这边,允许给每一段动画分别设置回调。设置动画回调,统一用OH_ArkUI_KeyframeAnimateOption_RegisterOnEventCallback(ArkUI_KeyframeAnimateOption* option, void* userData, void (*event)(void* userData), int32_t index)方法:

在回调函数也即上面的闭包函数中,我们便可以编写动画相关的代码,比如改变目标组件的尺寸或颜色等等。

3.4、注册动画结束回调

动画播放结束,是一个非常关键的事件,所以,少不了设置对应的回调,在关键帧动画这边,是用OH_ArkUI_KeyframeAnimateOption_RegisterOnFinishCallback(ArkUI_KeyframeAnimateOption* option, void* userData, void (*onFinish)(void* userData))方法进行处理的,在闭包函数中,我们便可以进行自定义处理,比如发送一些消息通知什么的,亦或者进行UI回显。

3.5、播放关键帧动画

上面的那些,说到底只是为关键帧动画进行必要的准备,并没有真正进行关键帧动画的播放,要进行播放就少不了用上 ArkUI_NativeAnimateAPI_1 指针。
在 ArkUI_NativeAnimateAPI_1 的函数成员中,有一个专门用于播放关键帧动画的int32_t (*keyframeAnimateTo)(ArkUI_ContextHandle context, ArkUI_KeyframeAnimateOption* option)方法。

二、动画实现

3、关键帧动画

既然关键帧动画的相关理论,或者说相关API,都已经认识了,那么,接下来便可以真刀真枪开始代码实践了,毕竟纸上得来终觉浅,躬行方知事原委。

3.1、自定义按钮形状


如图所示,此次关键帧动画的作用对象,是一个按钮、圆形的按钮,然而,无论是 ArkTS 代码还是 C++,按钮组件的默认形状,都不是圆形的,而是胶囊形的,要改变按钮形状,就必须显式地设置按钮形状。

为了支持按钮形状的自定义设置,需要在 ArkUIButtonNode.h 中新增如下的一个公共方法:

voidSetButtonType(ArkUI_ButtonType type){assert(handle_);ArkUI_NumberValue value[]={{.i32=type}};ArkUI_AttributeItem item={value,1};nativeModule_->setAttribute(handle_,NODE_BUTTON_TYPE,&item);}

而在 ArkUI_ButtonType 枚举类中,所有的按钮形状有如下:

3.2、实现页面结构

在编写有关关键帧动画的代码之前,先把页面整体结构给实现出来。如上图所示,除去 ArkTS 实现的部分页面结构外,剩下的是一个按钮,而这个按钮实际上可以放在一个看不见的 Column 中:

这里特别提醒一下,在 DevEco Studio 中,实际上是有一个可以专门分析页面结构的 ArkUI Inspector 工具的,工具入口默认位置在 IDE 界面左下角的位置,跟日志工具的入口挨着。

实现这部分C++代码实现的页面结构,不妨放在testKeyFrameAnimate方法体中:

std::shared_ptr<ArkUIButtonNode>g_keyFrame_button=nullptr;std::shared_ptr<ArkUIBaseNode>testKeyFrameAnimate(){autocolumn=std::make_shared<ArkUIColumnNode>();column->SetPercentWidth(1.0f);column->SetPercentHeight(1.0f);autobutton=std::make_shared<ArkUIButtonNode>();button->SetEnable();button->SetButtonType(ARKUI_BUTTON_TYPE_CIRCLE);button->SetWidth(150);button->SetHeight(150);button->SetBackgroundColor(0xFF000000);button->SetLabel("Click");button->SetMargin(20.0,0.0,0.0,0.0);g_keyFrame_button=button;column->AddChild(button);returncolumn;}

很简单的一段代码。

3.3、实现关键帧动画

既然作用对象是一个按钮,不妨将关键帧动画的实现代码,全都放在按钮点击事件的回调处理函数中:

// 注册按钮点击事件button->RegisterNodeEvent(button->GetHandle(),NODE_ON_CLICK,1,nullptr);// 定义按钮点击处理回调函数autoonClick=[](ArkUI_NodeEvent*event){showUITextCallback("关键帧动画","开始演示");// 设置ArkUI_KeyframeAnimateOption参数staticArkUI_KeyframeAnimateOption*option=OH_ArkUI_KeyframeAnimateOption_Create(2);// 关键帧动画状态数OH_ArkUI_KeyframeAnimateOption_SetDuration(option,2000,0);// 第一段关键帧动画的持续时间OH_ArkUI_KeyframeAnimateOption_SetDuration(option,2000,1);// 第二段关键帧动画的持续时间OH_ArkUI_KeyframeAnimateOption_SetIterations(option,5);// 关键帧动画播放次数OH_ArkUI_KeyframeAnimateOption_RegisterOnEventCallback(option,nullptr,[](void*user){showUITextCallback("关键帧动画","放大按钮");g_keyFrame_button->SetWidth(200);g_keyFrame_button->SetHeight(200);},0);// 第一段关键帧时刻状态的闭包函数OH_ArkUI_KeyframeAnimateOption_RegisterOnEventCallback(option,nullptr,[](void*user){showUITextCallback("关键帧动画","缩小按钮");g_keyFrame_button->SetWidth(80);g_keyFrame_button->SetHeight(80);},1);// 第二段关键帧时刻状态的闭包函数OH_ArkUI_KeyframeAnimateOption_RegisterOnFinishCallback(option,nullptr,[](void*user){showUITextCallback("关键帧动画","结束演示");OH_LOG_Print(LOG_APP,LOG_INFO,LOG_PRINT_DOMAIN,"Manager","keyframe animate finish");});// 关键帧动画结束回调ArkUI_ExpectedFrameRateRange*range=newArkUI_ExpectedFrameRateRange;range->max=120;range->expected=60;range->min=30;OH_ArkUI_KeyframeAnimateOption_SetExpectedFrameRate(option,range);// 关键帧设置期望帧率// 获取ArkUI_NativeAnimateAPI接口autoanimateApi=NativeModuleInstance::GetInstance()->GetNativeAnimateAPI();// 获取context对象staticArkUI_ContextHandle context=nullptr;context=OH_ArkUI_GetContextByNode(g_keyFrame_button->GetHandle());// 执行对应的动画animateApi->keyframeAnimateTo(context,option);};// 设置按钮点击事件接收器button->RegisterNodeEventReceiver(onClick);

与之前一样,用一个全局的g_keyFrame_button变量,去持有按钮组件节点的实例,从而方便在闭包函数中,动态地设置按钮的尺寸——OH_ArkUI_KeyframeAnimateOption_RegisterOnEventCallback的闭包函数体中,以及执行animateApi->keyframeAnimateTo(context, option)前获取按钮组件对应的上下文信息。

3.4、真机演示

修改 NativeEntry.cpp 中 CreateNativeRoot 方法中的根节点代码:

napi_valueCreateNativeRoot(napi_env env,napi_callback_info info){size_t argc=1;napi_value args[1]={nullptr};napi_get_cb_info(env,info,&argc,args,nullptr,nullptr);// 获取 NodeContentArkUI_NodeContentHandle contentHandle;OH_ArkUI_GetNodeContentFromNapiValue(env,args[0],&contentHandle);NativeEntry::GetInstance()->SetContentHandle(contentHandle);// 创建文本列表// auto list = CreateTextListExample();// NativeEntry::GetInstance()->SetRootNode(list);// 创建 Column// auto column = testGestureExample();// NativeEntry::GetInstance()->SetRootNode(column);// 创建 image// auto image = CreateDragImageExample();// NativeEntry::GetInstance()->SetRootNode(image);// 演示动画// auto column = testFrameAnimate();// NativeEntry::GetInstance()->SetRootNode(column);// auto column = testPropertiesAnimate();// NativeEntry::GetInstance()->SetRootNode(column);// auto column = testTransitionAnimate();// NativeEntry::GetInstance()->SetRootNode(column);autocolumn=testKeyFrameAnimate();NativeEntry::GetInstance()->SetRootNode(column);returnnullptr;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 11:29:52

当算法遇上极限:2025 年计算机科学六大颠覆性突破

【摘要】2025 年多项成果被视为“极限之上的再突破”&#xff0c;重塑算法、AI 与工程实践的边界。引言2025 年对计算机科学从业者并不轻松。许多看了十几年的教科书观点被改写&#xff0c;原先被放进“理论极限”抽屉里的问题重新回到白板&#xff0c;人工智能在多个方向上走到…

作者头像 李华
网站建设 2026/4/16 12:55:25

Docker Compose 部署 MySQL 多实例 日常运维全指南

文章目录 Docker Compose部署MySQL多实例 日常运维全指南 一、基础运维核心指令(容器+MySQL实例) 1. 容器层面运维(Docker Compose操作) (1)实例状态与日志查看 (2)实例启停/重启/删除 (3)进入容器(调试/临时操作) 2. MySQL实例层面运维(数据库操作) (1)登录My…

作者头像 李华
网站建设 2026/4/3 3:45:38

学长亲荐10个AI论文工具,本科生轻松搞定论文格式!

学长亲荐10个AI论文工具&#xff0c;本科生轻松搞定论文格式&#xff01; AI 工具如何让论文写作更轻松&#xff1f; 在如今的学术环境中&#xff0c;越来越多的本科生开始借助 AI 工具来提升论文写作效率。无论是查找资料、撰写大纲&#xff0c;还是进行内容优化和降重处理&am…

作者头像 李华
网站建设 2026/4/18 7:38:28

msdatrep.ocx损坏丢失 无法运行软件 下载方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/4/18 1:57:22

YOLO模型训练支持Knowledge Distillation知识蒸馏

YOLO模型训练支持知识蒸馏 在工业质检、智能安防和自动驾驶等实际场景中&#xff0c;我们常常面临一个两难问题&#xff1a;大模型精度高但难以部署&#xff0c;小模型速度快却性能不足。尤其是在边缘设备上运行目标检测任务时&#xff0c;算力、内存和功耗的限制让很多高性能模…

作者头像 李华
网站建设 2026/4/18 1:59:17

YOLOv7-Wide改进版:宽度扩展带来精度飞跃

YOLOv7-Wide改进版&#xff1a;宽度扩展带来精度飞跃 在工业质检的产线上&#xff0c;一台摄像头正以每分钟300帧的速度扫描着高速移动的金属零件。突然&#xff0c;一个仅占几个像素点的微小裂纹被精准识别并触发剔除机制——这背后&#xff0c;正是现代目标检测模型对“精度”…

作者头像 李华