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

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi