HarmonyOS:ArkTS 显式动画 animateTo 自学指南

简介: 本文深入解析了 ArkTS 中的 `animateTo` 全局显式动画接口,帮助开发者掌握其使用方法。文章从接口概述、参数详解到使用注意事项,结合实际示例代码,全面展示了如何通过配置 `AnimateParam` 对象实现流畅的动画效果。内容涵盖属性动画、布局变化及组件转场等场景,并强调不同版本的支持特性。适合初学者系统学习,也供进阶开发者参考优化动画体验。希望本文能助你快速上手 `animateTo`!

在最近的项目开发工作中,我频繁需要为界面元素添加过渡动画效果,以提升用户体验。在这个过程中,我接触到了 ArkTS 提供的 ​​animateTo​​​ 全局显式动画接口。它为由于闭包代码导致的状态变化插入过渡动效提供了便捷的方式,能让布局类的宽高变化以及内容呈现出流畅的动画效果。然而,这个接口的使用细节和相关参数较多,文档虽然详细但较为零散,对于初学者来说理解和掌握起来有一定难度。因此,我决定撰写这篇博客,将自己的学习经验和理解整理成一份自学指南,希望能帮助其他开发者更快速、深入地掌握 ​​animateTo​​ 接口的使用。

一、​​animateTo​​ 接口概述

​animateTo​​​ 接口提供了一种显式的方式来为状态变化添加过渡动画。它支持属性动画、布局类的宽高变化动画等。不过需要注意的是,默认情况下内容(如文字、Canvas 内容)会直接到达终点状态,若要让内容跟随宽高变化,可以使用 ​​renderFit​​ 属性进行配置。

支持版本

  • 从 API Version 7 开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
  • 从 API version 9 开始,该接口支持在 ArkTS 卡片中使用。
  • 从 API version 10 开始,可以通过使用 ​​UIContext​​​ 中的 ​​animateTo​​ 来明确 UI 的执行上下文。
  • 从 API version 11 开始,该接口支持在元服务中使用。

接口定义

typescript

animateTo(value: AnimateParam, event: () => void): void
  • 参数说明
  • ​value​​​:​​AnimateParam​​ 类型,必填,用于设置动画效果相关参数。
  • ​event​​​:​​() => void​​ 类型,必填,指定动效的闭包函数,在闭包函数中导致的状态变化系统会自动插入过渡动画。

二、​​AnimateParam​​ 对象详细说明

​AnimateParam​​ 对象包含了多个用于配置动画效果的参数,下面是各个参数的详细介绍:

1. ​​duration​

  • 类型:​​number​
  • 是否必填:否
  • 描述:动画持续时间,单位为毫秒。默认值为 1000。
  • 在 ArkTS 卡片上最大动画持续时间为 1000 毫秒,若超出则固定为 1000 毫秒。
  • 设置小于 0 的值时按 0 处理。
  • 设置浮点型类型的值时,向下取整。例如,设置值为 1.2,按照 1 处理。

2. ​​tempo​

  • 类型:​​number​
  • 是否必填:否
  • 描述:动画播放速度,值越大动画播放越快,值越小播放越慢,为 0 时无动画效果。默认值为 1.0。当设置小于 0 的值时按值为 1 处理。

3. ​​curve​

  • 类型:​​Curve | ICurve9+ | string​
  • 是否必填:否
  • 描述:动画曲线。默认值为 ​​Curve.EaseInOut​​。

4. ​​delay​

  • 类型:​​number​
  • 是否必填:否
  • 描述:动画延迟播放时间,单位为 ms(毫秒),默认不延时播放。默认值为 0,取值范围为 ​​(-∞, +∞)​​。
  • ​delay >= 0​​​ 为延迟播放,​​delay < 0​​​ 表示提前播放。对于 ​​delay < 0​​​ 的情况:当 ​​delay​​​ 的绝对值小于实际动画时长,动画将在开始后第一帧直接运动到 ​​delay​​​ 绝对值的时刻的状态;当 ​​delay​​ 的绝对值大于等于实际动画时长,动画将在开始后第一帧直接运动到终点状态。其中实际动画时长等于单次动画时长乘以动画播放次数。
  • 设置浮点型类型的值时,向下取整。例如,设置值为 1.2,按照 1 处理。

5. ​​iterations​

  • 类型:​​number​
  • 是否必填:否
  • 描述:动画播放次数。默认播放一次,设置为 -1 时表示无限次播放。设置为 0 时表示无动画效果。默认值为 1,取值范围为 ​​[-1, +∞)​​。

6. ​​playMode​

  • 类型:​​PlayMode​
  • 是否必填:否
  • 描述:动画播放模式,默认播放完成后重头开始播放。默认值为 ​​PlayMode.Normal​​。
  • 推荐使用 ​​PlayMode.Normal​​​ 和 ​​PlayMode.Alternate​​​,此场景下动画的第一轮是正向播放的。如使用 ​​PlayMode.Reverse​​​ 和 ​​PlayMode.AlternateReverse​​,则动画的第一轮是逆向播放的,在动画刚开始时会跳变到终止状态,然后逆向播放动画。
  • 使用 ​​PlayMode.Alternate​​​ 或 ​​PlayMode.AlternateReverse​​​ 时,开发者应保证动画最终状态和状态变量的取值一致,即应保证动画的最后一轮是正向播放的。使用 ​​PlayMode.Alternate​​​ 时,​​iterations​​​ 应为奇数。使用 ​​PlayMode.AlternateReverse​​​ 时,​​iterations​​ 应为偶数。
  • 不推荐使用 ​​PlayMode.Reverse​​,此场景下不仅会导致动画刚开始就跳变到终止状态,也会导致动画最终状态和状态变量的取值不同。

7. ​​onFinish​

  • 类型:​​() => void​
  • 是否必填:否
  • 描述:动画播放完成回调。UIAbility 从前台切换至后台时会立即结束仍在步进中的有限循环动画,触发播放完成回调。

8. ​​finishCallbackType11+​

  • 类型:​​FinishCallbackType​
  • 是否必填:否
  • 描述:在动画中定义 ​​onFinish​​​ 回调的类型。默认值为 ​​FinishCallbackType.REMOVED​​。
  • ​FinishCallbackType​说明
  • ​REMOVED​​:当整个动画结束并立即删除时,将触发回调。
  • ​LOGICALLY​​:当动画在逻辑上处于下降状态,但可能仍处于其长尾状态时,将触发回调。

9. ​​expectedFrameRateRange11+​

  • 类型:​​ExpectedFrameRateRange​
  • 是否必填:否
  • 描述:设置动画的期望帧率。
  • ​ExpectedFrameRateRange​说明

  • ​min​​:期望的最小帧率。

  • ​max​​:期望的最大帧率。
  • ​expected​​:期望的最优帧率。

三、使用注意事项

  • 在 ​​duration​​ 为 0 的动画闭包函数中改变属性,可以实现停止该属性动画的效果。
  • 如果需要在组件出现时创建动画,可以在 ​​onAppear​​​ 中实现动画的创建。不推荐在 ​​aboutToAppear​​​、​​aboutToDisappear​​​ 中调用动画。因为在 ​​aboutToAppear​​​ 中调用动画,自定义组件内的 ​​build​​​ 还未执行,内部组件还未创建,动画时机过早,动画属性没有初值无法对组件产生动画;执行 ​​aboutToDisappear​​​ 时,组件即将销毁,不能在 ​​aboutToDisappear​​ 里面做动画。
  • 也可以使用组件内转场,在组件出现和消失时做动画。组件内转场不支持的属性,可以使用 ​​animateTo​​ 实现组件消失动画效果。

四、示例代码

示例 1:设置动画在 ​​onAppear​​ 中执行

// xxx.ets
@Entry
@Component
struct AnimateToExample {
  @State widthSize: number = 300
  @State heightSize: number = 120
  @State rotateAngle: number = 0
  private flag: boolean = true

  build() {
    Column() {
      Button('change size')
        .width(this.widthSize)
        .height(this.heightSize)
        .margin(40)
        .onClick(() => {
          if (this.flag) {
            // 建议使用this.getUIContext()?.animateTo()
            animateTo({
              duration: 2500,
              curve: Curve.EaseIn,
              iterations: 4,
              playMode: PlayMode.Normal,
              onFinish: () => {
                console.info('play end')
              }
            }, () => {
              this.widthSize = 180
              this.heightSize = 80
            })
          } else {
            // 建议使用this.getUIContext()?.animateTo()
            animateTo({}, () => {
              this.widthSize = 300
              this.heightSize = 120
            })
          }
          this.flag = !this.flag
        })
      Button('stop rotating')
        .margin(60)
        .rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle })
        .onAppear(() => {
          // 组件出现时开始做动画
          // 建议使用this.getUIContext()?.animateTo()
          animateTo({
            duration: 1500,
            curve: Curve.EaseIn,
            delay: 600,
            iterations: -1, // 设置-1表示动画无限循环
            playMode: PlayMode.Alternate,
            expectedFrameRateRange: {
              min: 15,
              max: 130,
              expected: 70,
            }
          }, () => {
            this.rotateAngle = 120
          })
        })
        .onClick(() => {
          // 建议使用this.getUIContext()?.animateTo()
          animateTo({ duration: 0 }, () => {
            // this.rotateAngle之前为120,在duration为0的动画中修改属性,可以停止该属性之前的动画,按新设置的属性显示
            this.rotateAngle = 0
          })
        })
    }.width('100%').margin({ top: 10 })
  }
}

2025-03-27 18-55-43.2025-03-27 18_56_04.gif

示例 2:动画执行结束后组件消失

// xxx.ets
@Entry
@Component
struct AttrAnimationExample {
  @State heightSize: number = 120;
  @State isShow: boolean = true;
  @State count: number = 0;
  private isToBottom: boolean = true; // 向下

  build() {
    Column() {
      if (this.isShow) {
        Column()
          .width(220)
          .height(this.heightSize)
          .backgroundColor('green')
          .onClick(() => {
            // 建议使用this.getUIContext()?.animateTo()
            animateTo({
              duration: 2200,
              curve: Curve.EaseInOut,
              iterations: 1,
              playMode: PlayMode.Normal,
              onFinish: () => {
                this.count--;
                if (this.count == 0 && !this.isToBottom) { // 组件只有在向下做完动画才会消失
                  this.isShow = false;
                }
              }
            }, () => {
              this.count++;
              if (this.isToBottom) {
                this.heightSize = 70;
              } else {
                this.heightSize = 120;
              }
              this.isToBottom = !this.isToBottom;
            })
          })
      }
    }.width('100%').height('100%').margin({ top: 10 })
    .justifyContent(FlexAlign.End)
  }
}

2025-03-27 18-58-49.2025-03-27 18_59_01.gif

通过以上的介绍和示例,相信你已经对 ArkTS 的 ​​animateTo​​​ 接口有了更深入的了解。在实际开发中,你可以根据具体需求灵活配置 ​​AnimateParam​​ 对象的参数,实现各种炫酷的动画效果。

最后如果这篇文章对你有帮助,希望您能关注,点赞,加收藏哦~~~~

目录
相关文章
|
3月前
|
JavaScript 开发者 索引
鸿蒙应用开发从入门到实战(九):ArkTS渲染控制
ArkTS拓展了TypeScript,可以结合ArkUI进行渲染控制,是的界面设计具有可编程性。本文简要描述鸿蒙应用开发中的条件渲染和循环渲染。
170 5
|
3月前
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
308 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
|
3月前
|
JavaScript
鸿蒙应用开发从入门到实战(八):ArkTS自定义组件语法
ArkUI除系统预置的组件外,还支持自定义组件。使用自定义组件,可使代码的结构更加清晰,并且能提高代码的复用性。
192 7
|
3月前
|
API
鸿蒙应用开发从入门到实战(七):ArkTS组件声明语法
《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实战等原创内容、欢迎关注!​本文从界面制作从组件声明开始,通过一个相对简单的案例来系统的学习 ArkTS 声明组件的语法。
127 2
|
3月前
|
JavaScript 前端开发 开发者
鸿蒙应用开发从入门到实战(六):ArkTS声明式UI和组件化
鸿蒙开发语言ArkTS在继承了Typescrip语法的基础上,主要扩展了声明式UI开发相关的能力。
174 1
|
3月前
|
开发框架 JavaScript 数据库
鸿蒙应用开发从入门到实战(四):ArkTS 语言概述
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。
316 0
|
4月前
|
移动开发 网络协议 小程序
鸿蒙NEXT即时通讯/IM系统RinbowTalk v2.4版发布,基于MobileIMSDK框架、ArkTS编写
RainbowTalk是一套基于开源即时通讯讯IM框架 MobileIMSDK 的产品级鸿蒙NEXT端IM系统。纯ArkTS编写、全新开发,没有套壳、也没走捷径,每一行代码都够“纯血”。与姊妹产品RainbowChat和RainbowChat-Web 技术同源,历经考验。
217 1
|
5月前
|
存储 SQL 前端开发
跟老卫学HarmonyOS开发:ArkTS关系型数据库开发
本节以“账本”为例,使用关系型数据库接口实现账单的增、删、改、查操作。通过创建ArkTSRdb应用,演示如何操作RdbStore进行数据管理,并结合界面按钮实现交互功能。
214 0
跟老卫学HarmonyOS开发:ArkTS关系型数据库开发
|
5月前
|
缓存 移动开发 网络协议
纯血鸿蒙NEXT即时通讯/IM系统:RinbowTalk正式发布,全源码、纯ArkTS编写
RainbowTalk是一套基于MobileIMSDK的产品级鸿蒙NEXT端IM系统,目前已正式发布。纯ArkTS、从零编写,无套壳、没走捷径,每一行代码都够“纯”(详见:《RainbowTalk详细介绍》)。 MobileIMSDK是一整套开源IM即时通讯框架,历经10年,超轻量级、高度提炼,一套API优雅支持 UDP 、TCP 、WebSocket 三种协议,支持 iOS、Android、H5、标准Java、小程序、Uniapp、鸿蒙NEXT,服务端基于Netty编写。
332 1
|
6月前
|
编译器 程序员 开发者
详解HarmonyOS NEXT系统中ArkTS和仓颉的混合开发
本文介绍了鸿蒙系统中ArkTs与仓颉语言的混合开发方法,讲解了如何通过DevEco Studio创建混合项目、目录结构特点及组件调用方式,强调编译器自动化处理大幅简化开发流程,提升了开发体验。