【鸿蒙HarmonyOS开发笔记】动画过渡效果之组件内转场动画,内含ForEach动画

概述

我们在开发中难免设计组件的插入、删除过程。通过组件内转场动画,可定义组件出现、消失的效果。

组件内转场动画的接口为:

transition(value: TransitionOptions)

transition函数的入参为组件内转场的效果,可以定义平移、透明度、旋转、缩放这几种转场样式的单个或者组合的转场效果,必须和animateTo一起使用才能产生组件转场效果。

transition常见用法

type用于指定当前的transition动效生效在组件的变化场景,类型为TransitionType

组件的插入、删除使用同一个动画效果

Button()
  .transition({ type: TransitionType.All, scale: { x: 0, y: 0 } })

type属性为TransitionType.All时,表示指定转场动效生效在组件的所有变化(插入和删除)场景。此时,删除动画和插入动画是相反的过程,删除动画是插入动画的逆播。

例如,以上代码定义了一个Button控件。在插入时,组件从scalex、y均为0的状态,变化到scalex、y均为1(即完整显示)的默认状态,以逐渐放大的方式出现。在删除时,组件从scalex、y均为1的默认状态,变化到指定的scalex、y均为0的状态,逐渐缩小至尺寸为0

组件的插入、删除使用不同的动画效果

Button()
  .transition({ type: TransitionType.Insert, translate: { x: 200, y: -200 }, opacity: 0 })
  .transition({ type: TransitionType.Delete, rotate: { x: 0, y: 0, z: 1, angle: 360 } })

当组件的插入和删除需要实现不同的转场动画效果时,可以调用两次transition函数,分别设置type属性为TransitionType.InsertTransitionType.Delete

例如,以上代码定义了一个Button控件。在插入时,组件从相对于组件正常布局位置x方向平移200vpy方向平移-200vp的位置、透明度为0的初始状态,变化到x、y方向平移量为0、透明度为1的默认状态,插入动画为平移动画和透明度动画的组合。在删除时,组件从旋转角为0的默认状态,变化到绕z轴旋转360度的终止状态,即绕z轴旋转一周。

只定义组件的插入或删除其中一种动画效果

Button()
  .transition({ type: TransitionType.Delete, translate: { x: 200, y: -200 } })

当只需要组件的插入或删除的转场动画效果时,仅需设置type属性为TransitionType.InsertTransitionType.Deletetransition效果。例如,以上代码定义了一个Button控件。删除时,组件从正常位置、没有平移的默认状态,变化到从相对于正常布局位置x方向平移200vpy方向平移-200vp的位置的状态。插入该组件并不会产生该组件的转场动画。


if/else产生组件内转场动画

if/else语句可以控制组件的插入和删除。如下代码即可通过Button的点击事件,控制if的条件是否满足,来控制if下的Image组件是否显示。

@Entry
@Component
struct IfElseTransition {
  @State flag: boolean = true;
  @State show: string = 'show';

  build() {
    Column() {
      Button(this.show).width(80).height(30).margin(30)
        .onClick(() => {
          if (this.flag) {
            this.show = 'hide';
          } else {
            this.show = 'show';
          }
          // 点击Button控制Image的显示和消失
          this.flag = !this.flag;
        })
      if (this.flag) {
          Image($r('app.media.mountain')).width(200).height(200)
      }
    }.height('100%').width('100%')
  }
}

以上代码没有配置任何动画。接下来,我们将给以上代码加入组件内转场的效果。首先Image组件是由if控制的组件,需要给其加上transition的参数,以指定组件内转场的具体效果。例如,可以如以下代码,给其插入时加上平移效果,删除时加上缩放和透明度效果。

if (this.flag) {
  Image($r('app.media.mountain')).width(200).height(200)
    .transition({ type: TransitionType.Insert, translate: { x: 200, y: -200 } })
    .transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })
}

以上代码虽然指定了动画的样式,但是未指定动画参数,尚不知道需要用多长时间、怎样的曲线完成该动画。transition必须配合animateTo一起使用,并在animateTo的闭包中,控制组件的插入、删除。

对于以上示例代码,即为在animateTo闭包中改变flag的值,该部分代码如下所示。指定动画时长为1000ms,曲线使用animateTo函数默认的曲线,改变flag的值。则由flag变化所引起的一切变化,都会按照该动画参数,产生动画。在这里,flag会影响Image的出现和消失。

animateTo({ duration: 1000 }, () => {
  this.flag = !this.flag;
})

经过以上过程,当animateTotransition一起使用时,即产生了组件内转场动画。完整示例代码如下:

@Entry
@Component
struct IfElseTransition {
  @State flag: boolean = true;
  @State show: string = 'show';

  build() {
    Column() {
      Button(this.show).width(80).height(30).margin(30)
        .onClick(() => {
          if (this.flag) {
            this.show = 'hide';
          } else {
            this.show = 'show';
          }
          
          animateTo({ duration: 1000 }, () => {
            // 动画闭包内控制Image组件的出现和消失
            this.flag = !this.flag;
          })
        })
      if (this.flag) {
        // Image的出现和消失配置为不同的过渡效果
        Image($r('app.media.mountain')).width(200).height(200)
          .transition({ type: TransitionType.Insert, translate: { x: 200, y: -200 } })
          .transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })
      }
    }.height('100%').width('100%')
  }
}

在这里插入图片描述

说明

当配置transition的效果为translatescale时,本身位置叠加上平移或放大倍数后,动画过程中有可能超过父组件的范围。如果超出父组件的范围时,希望子组件完整的显示,那么可以设置父组件的clip属性为false,使父组件不对子组件产生裁剪。如果超出父组件的范围时,希望超出的子组件部分不显示,那么可以设置父组件的clip属性为true,裁剪掉子组件超出的部分。


**ForEach**产生组件内转场动画

if/else类似,ForEach可以通过控制数组中的元素个数,来控制组件的插入和删除。通过ForEach来产生组件内转场动画,仍然需要两个条件:

ForEach里的组件配置了transition效果

animateTo的闭包中控制组件的插入或删除,即控制数组的元素添加和删除。

以下代码是使用ForEach产生组件内转场动画的一个示例。

@Entry
@Component
struct ForEachTransition {
  @State numbers: string[] = ["1", "2", "3", "4", "5"]
  startNumber: number = 6;

  build() {
    Column({ space: 10 }) {
      Column() {
        ForEach(this.numbers, (item) => {
          // ForEach下的直接组件需配置transition效果
          Text(item)
            .width(240)
            .height(60)
            .fontSize(18)
            .borderWidth(1)
            .backgroundColor(Color.Orange)
            .textAlign(TextAlign.Center)
            .transition({ type: TransitionType.All, translate: { x: 200 }, scale: { x: 0, y: 0 } })
        }, item => item)
      }
      .margin(10)
      .justifyContent(FlexAlign.Start)
      .alignItems(HorizontalAlign.Center)
      .width("90%")
      .height("70%")

      Button('向头部添加元素')
        .fontSize(16)
        .width(160)
        .onClick(() => {
          animateTo({ duration: 1000 }, () => {
            // 往数组头部插入一个元素,导致ForEach在头部增加对应的组件
            this.numbers.unshift(this.startNumber.toString());
            this.startNumber++;
          })
        })
      Button('向尾部添加元素')
        .width(160)
        .fontSize(16)
        .onClick(() => {
          animateTo({ duration: 1000 }, () => {
            // 往数组尾部插入一个元素,导致ForEach在尾部增加对应的组件
            this.numbers.push(this.startNumber.toString());
            this.startNumber++;
          })
        })
      Button('删除头部元素')
        .width(160)
        .fontSize(16)
        .onClick(() => {
          animateTo({ duration: 1000 }, () => {
            // 删除数组的头部元素,导致ForEach删除头部的组件
            this.numbers.shift();
          })
        })
      Button('删除尾部元素')
        .width(160)
        .fontSize(16)
        .onClick(() => {
          animateTo({ duration: 1000 }, () => {
            // 删除数组的尾部元素,导致ForEach删除尾部的组件
            this.numbers.pop();
          })
        })
    }
    .width('100%')
    .height('100%')
  }
}

效果如下图:
在这里插入图片描述
由于Column布局方式设为了FlexAlign.Start,即竖直方向从头部开始布局。所以往数组末尾添加元素时,并不会对数组中现存元素对应的组件位置造成影响,只会触发新增组件的插入动画。而往数组头部添加元素时,原来数组中的所有元素的下标都增加了,虽然不会触发其添加或者删除,但是会影响到对应组件的位置。所以除新增的组件会做transition动画以外,之前存在于ForEach中组件也会做位置动画。

说明

if/elseForEach为语法节点,配置组件内转场效果的组件应直接作为语法节点的孩子。由语法节点的增删引起的组件增删,只能触发其直接孩子组件的组件内转场动画,开发者不应期望其对更深层次的组件产生组件转场动画。

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

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

相关文章

AI论文速读 | UniTS:构建统一的时间序列模型

题目:UniTS: Building a Unified Time Series Model 作者:Shanghua Gao(高尚华), Teddy Koker, Owen Queen, Thomas Hartvigsen, Theodoros Tsiligkaridis, Marinka Zitnik 机构:哈佛大学(Harvard&#x…

如何监听抖音、快手、哔哩哔哩弹幕实现弹幕游戏制作?直播互动助手开放 API 帮你快速构建详细教程

弹幕直播概述 如何监听抖音、快手、哔哩哔哩弹幕实现弹幕游戏制作?随着中短视频平台直播热度的攀升,基于弹幕监听的直播模式也逐渐让大家熟知。如何去进行弹幕直播,去实现基于弹幕和礼物的直播新模式。边缘骇客直播互动助手是一款兼容大部分…

第四百一十回

文章目录 1. 概念介绍2. 方法与细节2.1 获取方法2.2 使用细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取当前系统语言"相关的内容,本章回中将介绍如何获取时间戳.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

U盘变本地磁盘?数据恢复有妙招!

一、U盘异变本地磁盘现象 在日常工作和生活中,U盘作为便携式的存储设备,广受大家喜爱。然而,有时我们会遇到一个奇怪的现象:原本应该显示为可移动磁盘的U盘,在插入电脑后却变成了“本地磁盘”。这种情况不仅让人困惑&…

解决:visio导出公式为pdf图片乱码问题

今天需要将Visio编辑好的以后的图输出pdf,但是点击保存后公式部分一直乱码,如下图所示 保存为pdf后会变成: 解决方案:保存时点击文件下方的快速打印,存到桌面,不要直接点击保存

【C++】三大特性之多态

1 定义及实现 1.1 概念 多态是C三大特性之一。通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。 多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如学…

代码资源集合

代码资源 通信QPSKOQPSKMSK信道编码GMSK 雷达LFM及干扰技术LFM射频噪声干扰噪声调幅干扰噪声调频干扰噪声调相干扰固定移频干扰间歇采样干扰 SAR成像RD算法CS算法wk算法 SAR干扰技术射频噪声干扰调幅噪声干扰调频噪声干扰调相噪声干扰噪声卷积干扰乘积干扰移频干扰 DOA估计功率…

雷龙科技Nand flash芯片试用体验

一、项目背景 最近自己开始准备了一个智能家居控制系统项目,需要包含室内的温湿度、空气质量、烟雾浓度以及气体含量,能够存储相应的数据,并进行显示。 Nand-flash存储器是flash存储器的一种,其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案…

微信视频号小店营业执照怎么办理?办理流程是什么?详细教程分享

大家好,我是电商花花。 现在视频号小店发展的这么好,越来越多的朋友都想加入到视频号小店电商行列。 而做视频号小店第一步就是要有企业营业执照,做视频号小店需要企业执照,因为个体户营业执照开的店铺,不能加入优选…

【Java】高级篇1:异常处理

异常:程序在执行过程中出现的非正常情况,如果不处理最终会导致JVM的非正常停止。 Java的异常抛出机制 Java异常体系 1、Throwable 2、Error和Exception 异常处理方式 1、try-catch-finally(捕获异常) 基本结构: 使用…

linux学习之Socket

目录 编写socket-udp 第一步,编写套接字 第二步,绑定端口号 第三步,启动服务器,读取数据 第四步,接收消息并发回信息给对方 编写socket-Tcp 第一步,编写套接字 第二步,绑定端口号 第三步…

2、高级语言的语法描述

常用的高级程序设计语言 程序语言的定义 语法 一组规则,用它可以形成和产生合适的程序 词法规则:单词符号的形成规则。 单词符号的形成规则单词符号是语言中具有独立意义的最基本结构 一般包括:常数、标识符、基本字、算符、界符等 描述工具:有限自动机…

蓝桥杯单片机快速开发笔记——超声波测距

一、原理分析 超声波测距是一种常见的测距方法,其原理是利用超声波在空气中传播的速度恒定且较快的特性,通过发送超声波信号并接收回波,计算出物体与传感器之间的距离。以下是超声波测距的原理和应用: 原理: 发送超声…

MyBookShopWeb第三波+书店商城asp.net+sqlserver

MyBookShopWeb第三波书店商城asp.netsqlserver 说明文档 运行前附加数据库.mdf(或sql生成数据库) 主要技术: 基于asp.net架构和sql server数据库,并采用三层架构 功能模块: 用户功能有首页 购买商品 购物车 我…

苍穹外卖-day04:项目实战-套餐管理(新增套餐,分页查询套餐,删除套餐,修改套餐,起售停售套餐)业务类似于菜品模块

苍穹外卖-day04 课程内容 新增套餐套餐分页查询删除套餐修改套餐起售停售套餐 要求: 根据产品原型进行需求分析,分析出业务规则设计接口梳理表之间的关系(分类表、菜品表、套餐表、口味表、套餐菜品关系表)根据接口设计进行代…

几个不错的 Jupyter Notebook 云端展示平台

jupyter nbviewer URL:https://nbviewer.jupyter.org/ 结合Github的示例用法&#xff1a;https://nbviewer.jupyter.org/github/ <用户名或者用户名/存放ipynb文件的仓库或者Gist ID> 例如&#xff1a;https://nbviewer.jupyter.org/github/yeshan333/JupyterNotebook…

通过点击按钮实现查看全屏和退出全屏的效果

动态效果如图&#xff1a; 可以通过点击按钮&#xff0c;或者esc键实现全屏和退出全屏的效果 实现代码&#xff1a; <template><div class"hello"><el-button click"fullScreen()" v-if"!isFullscreen">查看全屏</el-butt…

登录远程SQLServer

1&#xff0c;登录格式: 服务器名称:192.168.0.104,1433 192.168.0.104&#xff1a;SQLServer所在远程PC的IP &#xff0c;&#xff1a;逗号分割IP与端口号 1433&#xff1a;SQLServer所使用的端口号&#xff08;默认为1433&#xff09;&#xff0c;当使用默认端口号时可以省…

《1w实盘and大盘基金预测 day6》

昨日预测完美&#xff0c;点位基本符合&#xff0c;我预测3052&#xff0c;实际最低3055。 走势也符合高平开&#xff0c;冲高回落&#xff0c;再反震荡上涨 大家可以观察我准不准哟&#xff5e;后面有我的一些写笔记、分享的网站。 关注公众号&#xff0c;了解各种理财预测内…

WanAndroid(鸿蒙版)开发的第三篇

前言 DevEco Studio版本&#xff1a;4.0.0.600 WanAndroid的API链接&#xff1a;玩Android 开放API-玩Android - wanandroid.com 其他篇文章参考&#xff1a; 1、WanAndroid(鸿蒙版)开发的第一篇 2、WanAndroid(鸿蒙版)开发的第二篇 3、WanAndroid(鸿蒙版)开发的第三篇 …