OpenHarmony动效示例-如何使用animateTo实现显式动画。

2024-03-30 06:28

本文主要是介绍OpenHarmony动效示例-如何使用animateTo实现显式动画。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

利用ArkUI组件不仅可以实现局部属性变化产生的属性动画,也可以实现父组件属性变化引起子组件产生过渡效果式的全局动画即显式动画。效果如图所示:

相关概念

  • 显式动画:提供全局animateTo显式动画接口来指定有闭包代码导致的状态变化插入过渡动画效果。
  • 属性动画:组件的通用属性发生变化时,可以创建属性动画进行渐变,提升用户体验。
  • Slider:滑动条组件,用来快速调节设置值,如音量、亮度等。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”),选择JS或者eTS语言开发。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

├──entry/src/main/ets                // 代码区
│  ├──common
│  │  └──constants
│  │     └──Const.ets                // 常量类
│  ├──entryability
│  │  └──EntryAbility.ts             // 程序入口类
│  ├──pages
│  │  └──Index.ets                   // 动效页面入口
│  ├──view
│  │  ├──AnimationWidgets.ets        // 动画组件
│  │  ├──CountController.ets         // 图标数量控制组件
│  │  └──IconAnimation.ets           // 图标属性动画组件
│  └──viewmodel
│     ├──IconItem.ets                // 图标类
│     ├──IconsModel.ets              // 图标数据模型
│     └──Point.ets                   // 图标坐标类
└──entry/src/main/resources          // 资源文件

页面入口

页面入口由AnimationWidgets(动效组件)、CountController(动效图标数量控制组件)组成。

其中CountController通过Slider滑动控制quantity(动效图标数量);AnimationWidgets根据quantity展示相应数量的图标,点击组件按钮后通过在animateTo的event闭包函数中改变mainFlag状态,跟mainFlag相关的样式属性的变化都会产生动画效果,代码如下所示:

// Index.ets
@Entry
@Component
struct Index {@State quantity: number = Common.IMAGES_MIN;@Provide iconModel: IconsModel = new IconsModel(this.quantity, Common.OFFSET_RADIUS);build() {Column() {// 动画组件AnimationWidgets({quantity: $quantity})// 图标数量控制组件CountController({quantity: $quantity})}
...}
}

CountController组件通过Slilder滑动控制动效图标的数量,最少3个图标,最多6个图标,示例代码如下所示:

// CountController.ets
@Component
export struct CountController {@Link quantity: number;build() {Column() {Row() {Text($r('app.string.count')).textStyle()Text(this.quantity).textStyle()}...Slider({value: this.quantity,min: Common.IMAGES_MIN,max: Common.IMAGES_TOTAL,step: 1,style: SliderStyle.InSet}).blockColor(Color.White).selectedColor('#007DFF').showSteps(true).trackThickness($r('app.float.size_20')).onChange((value: number) => {this.quantity = value;})...}}
}

显式动画

点击AnimationWidgets组件的中心图标,调用animateTo方法,在event回调方法中改变状态,从而对组件本身产生缩放动画,和图标位置变化的动画效果,效果如下所示:

在animationTo的回调中修改mainFlag状态,所有跟mainFlag状态相关的属性变化都会产生过渡动画效果。代码如下所示:

// AnimationWidgets.ets
import { IconsModel } from '../viewmodel/IconsModel';
import { IconAnimation } from './IconAnimation';
import Common from '../common/constants/Const';
import IconItem from '../viewmodel/IconItem';@Component
export struct AnimationWidgets {@State mainFlag: boolean = false;@Link @Watch('onQuantityChange') quantity: number;@Consume iconModel: IconsModel;onQuantityChange() {this.iconModel.addImage(this.quantity);}aboutToAppear() {this.onQuantityChange();}animate() {animateTo({delay: Common.DELAY_10,tempo: Common.TEMPO,iterations: 1,duration: Common.DURATION_500,curve: Curve.Smooth,playMode: PlayMode.Normal}, () => {this.mainFlag = !this.mainFlag;})}build() {Stack() {Stack() {ForEach(this.iconModel.imagerArr, (item: IconItem) => {IconAnimation({item: item,mainFlag: $mainFlag})}, (item: IconItem) => JSON.stringify(item.index))}.width(Common.DEFAULT_FULL_WIDTH).height(Common.DEFAULT_FULL_HEIGHT).rotate({x: 0,y: 0,z: 1,angle: this.mainFlag ? Common.ROTATE_ANGLE_360 : 0})Image(this.mainFlag? $r("app.media.imgActive"): $r("app.media.imgInit")).width($r('app.float.size_64')).height($r('app.float.size_64')).objectFit(ImageFit.Contain).scale({x: this.mainFlag ? Common.INIT_SCALE : 1,y: this.mainFlag ? Common.INIT_SCALE : 1}).onClick(() => {this.iconModel.reset();this.animate();})Text($r('app.string.please_click_button')).fontSize($r('app.float.size_16')).opacity(Common.OPACITY_06).fontColor($r('app.color.fontGrayColor')).fontWeight(Common.FONT_WEIGHT_500).margin({top: $r('app.float.size_100')})}.width(Common.DEFAULT_FULL_WIDTH).layoutWeight(1)}
}

属性动画

组件的通用属性发生变化时,可以创建属性动画进行渐变,提升用户体验。示例效果如下所示:


当组件由animation动画属性修饰时,如果自身属性发生变化会产生过渡动画效果。本示例中当点击小图标时会触发自身clicked状态的变化,所有跟clicked相关的属性变化(如translate、rotate、scale、opacity)都会被增加动画效果。代码如下所示:

// IconAnimation.ets
export struct IconAnimation {@Link mainFlag: boolean;@ObjectLink item: IconItem;build() {Image(this.item.image).width(Common.ICON_WIDTH).height(Common.ICON_HEIGHT).objectFit(ImageFit.Contain).translate(this.mainFlag? { x: this.item.point.x, y: this.item.point.y }: { x: 0, y: 0 }).rotate({x: 0,y: 1,z: 0,angle: this.item.clicked ? Common.ROTATE_ANGLE_360 : 0}).scale(this.item.clicked? { x: Common.SCALE_RATIO, y: Common.SCALE_RATIO }: { x: 1, y: 1 }).opacity(this.item.clicked ? Common.OPACITY_06 : 1).onClick(() => {this.item.clicked = !this.item.clicked;}).animation({delay: Common.DELAY_10,duration: Common.DURATION_1000,iterations: 1,curve: Curve.Smooth,playMode: PlayMode.Normal})}
}

根据图标数量计算图标位置代码如下所示:

// IconsModel.ets
import Common from '../common/constants/Const';
import IconItem from './IconItem';
import Point from './Point';const TWO_PI: number = 2 * Math.PI;@Observed
export class IconsModel {public imagerArr: Array<IconItem> = [];private num: number = Common.IMAGES_MIN;private radius: number;constructor(num: number, radius: number) {this.radius = radius;this.addImage(num);}public addImage(num: number) {this.num = num;if (this.imagerArr.length == num) {return;}if (this.imagerArr.length > num) {this.imagerArr.splice(num, this.imagerArr.length - num);} else {for (let i = this.imagerArr.length; i < num; i++) {const point = this.genPointByIndex(i);this.imagerArr.push(new IconItem(i, Common.IMAGE_RESOURCE[i], false, point));}}this.refreshPoint(num);}public refreshPoint(num: number) {for (let i = 0; i < num; i++) {this.imagerArr[i].point = this.genPointByIndex(i);}}public genPointByIndex(index: number): Point {const x = this.radius * Math.cos(TWO_PI * index / this.num);const y = this.radius * Math.sin(TWO_PI * index / this.num);return new Point(x, y);}public reset() {for (let i = 0; i < this.num; i++) {if (this.imagerArr[i].clicked) {this.imagerArr[i].clicked = false;}}}
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 如何使用animateTo实现显式动画。
  2. 如何使用animation为组件添加属性动画。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?《鸿蒙基础入门学习指南》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

这篇关于OpenHarmony动效示例-如何使用animateTo实现显式动画。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860721

相关文章

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2