鸿蒙开发运用ArkUI基础-实操显式动画

利用ArkUI组件不仅可以实现属性变化引起的属性动画,也可以实现父组件状态变化引起子组件产生动画效果,这种动画为显式动画。效果如图所示:

代码结构解读

├──entry/src/main/ets                // 代码区
│  ├──common
│  │  └──constants
│  │     └──Const.ets                // 常量类
│  ├──entryability
│  │  └──EntryAbility.ts             // 程序入口类
│  ├──pages
│  │  └──Index.ets                   // 动效页面入口
│  ├──view
│  │  ├──AnimationWidgets.ets        // 动画组件
│  │  ├──CountController.ets         // 图标数量控制组件
│  │  └──IconAnimation.ets           // 图标属性动画组件
│  └──viewmodel
│     ├──IconItem.ets                // 图标类
│     ├──Point.ets                   // 图标坐标类
│     └──IconsModel.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($r('app.color.SliderSelectColor'))
        .showSteps(true)
        .trackThickness($r('app.float.size_20'))
        .onChange((value: number) => {
          this.quantity = value;
        })
        ...
    }
  }
}

显式动画

点击AnimationWidgets组件的中心图标,调用animateTo方法,在event回调方法中改变状态,从而对组件本身产生缩放动画,和图标位置变化的动画效果,效果如图所示: 在animationTo的回调中修改mainFlag状态,所有跟mainFlag状态相关的属性变化都会产生过渡动画效果。

// AnimationWidgets.ets
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))
      }
      .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")
      )
        .scale({
          x: this.mainFlag ? Common.INIT_SCALE : 1,
          y: this.mainFlag ? Common.INIT_SCALE : 1
        })
        .onClick(() => {
          this.iconModel.reset(); //  重置图标激活状态
          this.animate(); // 启动显式动画
        })
      ...
    }
  }
}

属性动画

组件的通用属性发生变化时,可以创建属性动画进行渐变,提升用户体验。示例效果如图所示: 当组件由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;
      }
    }
  }
}

本文是对鸿蒙开发(ArkTS)基础知识运用,显式动画实操。更多鸿蒙开发到的技术解析可以前往《鸿蒙Harmony4.0开发基础-高阶》,下面是知识分布路线图。高清完整版点击前往保存。

最后

利用ArkUI组件实现父组件状态变化引起子组件产生动画效果,这种动画为显式动画。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/259734.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

css 美化滚动条

当div内容溢出容器定义的高度时,滚动条显示,并美化默认的滚动条样式 div 容器 <divclass"content">内容 </div>css 样式 /* 问话区域 滚动条 */ .content {overflow: auto;height: 662px;padding: 25px;scrollbar-width: thin; /* 设置滚动条宽度 */bo…

四川云汇优想教育咨询有限公司电商服务靠谱吗

随着抖音电商的兴起&#xff0c;越来越多的商家开始关注这一领域。四川云汇优想教育咨询有限公司作为一家专注于电商服务的企业&#xff0c;也受到了广泛的关注。那么&#xff0c;四川云汇优想教育咨询有限公司的抖音电商服务靠谱吗&#xff1f;下面我们将从多个方面进行深入剖…

大模型赋能“AI+电商”,景联文科技提供高质量电商场景数据

据新闻报道&#xff0c;阿里巴巴旗下淘天集团和国际数字商业集团都已建立完整的AI团队。 淘天集团已经推出模特图智能生成、官方客服机器人、万相台无界版等AI工具&#xff0c;训练出了自己的大模型产品 “星辰”&#xff1b; 阿里国际商业集团已成立AI Business&#xff0c;…

在线教育(内部)培训系统搭建,提供高效便捷的学习体验

我国一直是教育大国&#xff0c;不管是国民义务教育&#xff0c;还是学历提升、职业证书等&#xff0c;我国教育行业一直处于兴盛不衰的地步。 随着互联网信息化的发展&#xff0c;在线教育培训系统逐渐在教育行业得到重视。根据数据显示&#xff0c;我国在线教育市场规模将达…

拼图游戏

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 创建一个代码类 和一个运行类 代码如下&#xff1a; package heima;import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import jav…

探索泰勒级数在机器学习中的作用:从函数逼近到模型优化

一、介绍 泰勒级数是数学中的一个基本概念&#xff0c;在机器学习领域有着重要的应用。本文将探讨泰勒级数的基础知识、它在机器学习中的相关性以及一些具体应用。 揭开复杂性&#xff1a;利用泰勒级数增强机器学习应用的理解和效率。 二、理解泰勒级数 在数学中&#xff0c;泰…

Leetcode—128.最长连续序列【中等】

2023每日刷题&#xff08;六十四&#xff09; Leetcode—128.最长连续序列 实现代码 class Solution { public:int longestConsecutive(vector<int>& nums) {unordered_set<int> s;for(auto num: nums) {s.insert(num);}int longestNum 0;for(auto num: s) …

Python Opencv实践 - 手部跟踪

使用mediapipe库做手部的实时跟踪&#xff0c;关于mediapipe的介绍,请自行百度。 mediapipe做手部检测的资料&#xff0c;可以参考这里&#xff1a; MediaPipe Hands: On-device Real-time Hand Tracking 论文阅读笔记 - 知乎论文地址&#xff1a; https://arxiv.org/abs/2006…

Shell三剑客:awk(简介)

一、前言 AWK 是一种编程语言&#xff0c;用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件&#xff0c;或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能&#xff0c;是linux/unix下的一个强大编程工具。它在命令行中使用&a…

3 - Electron app BrowserWindow对象-关于窗口

优雅的打开应用~ 当加载缓慢&#xff0c;打开应用的一瞬间会出现白屏&#xff0c;以下方法可以解决 const mainWindow new BrowserWindow({ show: false }) mainWindow.once(ready-to-show, () > {mainWindow.show() }) 设置背景颜色 const win new BrowserWindow({ b…

VueCron使用方法

1&#xff09;什么是vueCron Vue Cron 是基于 Vue.js 的定时任务管理组件&#xff0c;它提供了一种简单易用的方式来设定和管理定时任务。Vue Cron 提供了一个类似于 Linux crontab 的界面&#xff0c;用户可以通过它来创建、编辑和删除定时任务。 2&#xff09;安装依赖及应…

FreeCodeCamp--数千免费编程入门教程,非盈利性网站,质量高且支持中文

在浏览话题“Github上获得Star最多的项目”时&#xff0c;看到了FreeCodeCamp&#xff0c;顾名思义--免费编程营地&#xff0c;于是就做了些调研&#xff0c;了解了下这是个什么项目 这是一个致力于推动编程教育的非营利性组织&#xff0c;团队由来自世界各地的杰出的技术开发…

如何将图片转为PDF

问题描述&#xff1a;如何将图片转为PDF&#xff0c;有时需要将纸质文档扫描成PDF&#xff0c;然后上传到网上。 解决办法&#xff1a;平时使用的方法是将图片插入到word文件中&#xff0c;然后将图片设置为浮于文字下方&#xff0c;然后调整图片的大小&#xff0c;铺满整个wo…

SMART PLC MODBUS-RTU通信(多台同一设备通信优化写法)

MODBUS通信基础介绍请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/133755924https://rxxw-control.blog.csdn.net/article/details/133755924多台同一设备的MODBUS-RTU通信,我们在编写轮询程序的时候,可以采用站号变址的方式实现。 1、轮询状态…

[Linux] Haproxy负载均衡集群

一、Haproxy知识 1.1 常用的负载均衡调度器 软件通常使用开源的LVS、Haproxy、 Nginx LVS性能最好&#xff0c;但是搭建相对复杂&#xff1b;Nginx 的upstream模块支持群集功能&#xff0c;但是对群集节点健康检查功能不强&#xff0c;高并发性能没有Haproxy好。 硬件一般使用…

java中常用的加密算法总结

目前在工作中常用到加密的一些场景&#xff0c;比如密码加密&#xff0c;数据加密&#xff0c;接口参数加密等&#xff0c;故通过本文总结以下常见的加密算法。 1. 对称加密算法 对称加密算法使用相同的密钥进行加密和解密。在Java中&#xff0c;常见的对称加密算法包括&…

2023_Spark_实验三十二:消费Kafka数据并保存到MySQL中

实验目的&#xff1a;掌握Scala开发工具消费Kafka数据&#xff0c;并将结果保存到关系型数据库中 实验方法&#xff1a;消费Kafka数据保存到MySQL中 实验步骤&#xff1a; 一、创建Job_ClickData_Process 代码如下&#xff1a; package examsimport org.apache.kafka.clien…

阶段十-springsecurity总结

jwt认证流程 SpringSecurity 认证过程 第一步&#xff1a; 创建一个类实现UserDetailsService接口&#xff0c;重写其中的方法 通过重写 public UserDetails loadUserByUsername(String username) 方法 从数据库校验用户输入的用户名 配置SecurityConfig Bean注入 Passwor…

【C++题目速刷】二分查找

【C题目速刷】二分查找 一、二分查找1、题目链接2、解题3、代码 二、在排序数组中查找元素的第一个和最后一个位置1、题目链接2、解题3、代码4、算法模板 三、x的平方根1、解题链接2、解题3、代码 四、搜索插入位置1、题目链接2、解题3、代码 五、山脉数组的峰顶索引1、题目链接…

论文解读:On the Integration of Self-Attention and Convolution

自注意力机制与卷积结合&#xff1a;On the Integration of Self-Attention and Convolution(CVPR2022) 引言 1&#xff1a;卷积可以接受比较大的图片的&#xff0c;但自注意力机制如果图片特别大的话&#xff0c;运算规模会特别大&#xff0c;即上图中右边(卷积)会算得比较快…