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​​ 对象的参数,实现各种炫酷的动画效果。

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

目录
相关文章
|
27天前
|
前端开发 API 开发者
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
本文由黑臂麒麟(6年前端经验)撰写,介绍ArkTS开发中的常用基础组件与布局组件。基础组件包括Text、Image、Button等,支持样式设置如字体颜色、大小和加粗等,并可通过Resource资源引用统一管理样式。布局组件涵盖Column、Row、List、Grid和Tabs等,支持灵活的主轴与交叉轴对齐方式、分割线设置及滚动事件监听。同时,Tabs组件可实现自定义样式与页签切换功能。内容结合代码示例,适合初学者快速上手ArkTS开发。参考华为开发者联盟官网基础课程。
153 75
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
|
28天前
|
数据管理 API 开发者
HarmonyOS:ArkTS RowSplit 组件自学指南
在 ArkTS 开发中,复杂界面布局需求常见,尤其需要灵活调整子组件宽度时,传统方式难以满足动态交互需求。`RowSplit` 组件解决了这一问题,支持横向布局并插入可拖动的分割线,让用户轻松调整子组件宽度,提升体验。本文详细介绍了 `RowSplit` 的功能、接口、属性及使用示例,帮助开发者掌握其用法,并总结了注意事项。通过合理配置,可实现灵活美观的布局效果。希望对您有帮助,欢迎关注、点赞和收藏!
75 31
|
28天前
|
API 开发者 UED
HarmonyOS:ArkTS 多态样式自学指南
本文介绍了 ArkTS 多态样式功能,帮助开发者为组件设置不同状态(如点击、按下、禁用等)下的样式。从 API Version 8 开始支持,API Version 11 引入 `attributeModifier` 动态设置属性。核心接口 `stateStyles` 支持多种状态,如 `normal`、`pressed`、`disabled` 等。文章通过示例代码展示了如何为 `Text` 和 `Radio` 组件设置多态样式,结合状态控制实现动态视觉反馈。掌握此功能可提升用户体验,推荐开发者根据需求灵活运用。
80 27
|
28天前
|
API 开发者
HarmonyOS:ArkTS Path 组件自学指南
在鸿蒙应用开发中,绘制复杂图形常面临传统布局方式难以满足需求的问题。ArkTS 的 Path 组件提供了解决方案,如同一把“神奇画笔”,支持通过灵活的命令和属性绘制直线、曲线、椭圆弧等多样图形。本文详细介绍了 Path 组件从 API Version 7 起的功能特性,包括 `commands`、`fill`、`stroke` 等核心属性,以及各类绘图命令如 `M`(移动)、`L`(直线)、`C`(贝塞尔曲线)等。结合示例代码,展示了如何绘制简单直线到复杂曲线图形,并拓展了颜色、透明度和线条样式的自定义方法。掌握 Path 组件,可为应用带来更丰富生动的视觉体验,助力开发者实现创意绘图需求。
74 21
|
17天前
|
缓存 开发工具 开发者
鸿蒙NEXT开发App相关工具类(ArkTs)
这段代码展示了一个名为鸿蒙NEXT开发 `AppUtil` 的工具类,主要用于管理鸿蒙应用的上下文、窗口、状态栏、导航栏等配置。它提供了多种功能,例如设置灰阶模式、颜色模式、字体类型、屏幕亮度、窗口属性等,并支持获取应用包信息(如版本号、包名等)。该工具类需在 UIAbility 的 `onWindowStageCreate` 方法中初始化,以便缓存全局变量。代码由鸿蒙布道师编写,适用于鸿蒙系统应用开发,帮助开发者更便捷地管理和配置应用界面及系统属性。
|
28天前
|
API 开发者 UED
HarmonyOS:ComposeTitleBar 组件自学指南
本文详解了鸿蒙开发中 ComposeTitleBar 组件的使用方法与技巧,从基础导入到属性配置,再到实际代码示例,帮助开发者构建美观实用的标题栏。组件自 API Version 10 起支持,具备独立功能结构,核心属性包括 `title`(必填)、`subtitle`(可选)和 `menuItems`(右侧菜单列表)。文章通过具体示例展示了如何配置标题、副标题及菜单项,并提供了交互优化、样式定制与多设备适配的建议。掌握这些内容,可显著提升应用界面体验。如果你有所收获,别忘了点赞收藏!
46 8
|
1月前
|
编解码 搜索推荐 API
鸿蒙栅格布局组件 GridRow 自学指南
在鸿蒙应用开发中,布局设计常因设备分辨率差异而面临挑战。传统固定布局可能导致组件挤压或显示错乱,而 GridRow 组件提供了灵活解决方案。它从 API Version 9 起支持栅格布局,搭配 GridCol 子组件实现强大适配能力。本文详解 GridRow 的参数、属性与事件,如 `columns`、`gutter`、`breakpoints` 等,并通过实战示例展示其应用。掌握 GridRow,助你轻松应对多尺寸设备布局需求,打造精美界面。
50 7
|
28天前
|
前端开发
鸿蒙开发:使用Rect绘制矩形
几何矩形,在实际的开发中,有多种的实现方式,并非一定需要Rect组件,但是,如果有需要用到矩形的场景,建议还是使用Rect组件,因为Rect组件自身携带了很多样式属性,可以满足我们日常的不同的需求。
鸿蒙开发:使用Rect绘制矩形
|
27天前
|
人工智能 物联网 Android开发
【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所有设置setting相关的页面-优雅草卓伊凡
【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所有设置setting相关的页面-优雅草卓伊凡
159 92
|
27天前
|
人工智能 物联网 Android开发
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
71 23
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡