HarmonyOS鸿蒙Next中如何使用animateTo和.animation实现UI动画效果?

HarmonyOS鸿蒙Next中如何使用animateTo和.animation实现UI动画效果? 我想为 HarmonyOS 应用添加动画效果,想了解:

  1. animateTo() 显式动画如何使用?如何设置 duration、curve、delay?

  2. .animation() 属性动画与 animateTo 有什么区别?

  3. 如何实现位移、缩放、旋转、透明度变化等动画?

  4. 常用的动画曲线(Curve.Linear、Curve.EaseInOut 等)有哪些?

  5. 如何实现组件出现/消失的过渡动画?

希望能获取常用动画效果的代码示例。

3 回复

实现思路:

  1. 使用 animateTo 显式动画,在回调中修改状态触发动画:
@State scale: number = 1;

Button('缩放')
  .scale({ x: this.scale, y: this.scale })
  .onClick(() => {
    animateTo({
      duration: 300,
      curve: Curve.EaseInOut
    }, () => {
      this.scale = this.scale === 1 ? 1.5 : 1;
    });
  })
  1. 使用 .animation 属性动画,自动对属性变化添加动画:
@State opacity: number = 1;

Button('透明度')
  .opacity(this.opacity)
  .animation({ duration: 500, curve: Curve.Linear })
  .onClick(() => {
    this.opacity = this.opacity === 1 ? 0.3 : 1;
  })
  1. 实现旋转动画:
@State angle: number = 0;

Image($r('app.media.icon'))
  .rotate({ angle: this.angle })
  .onClick(() => {
    animateTo({ duration: 500 }, () => {
      this.angle += 360;
    });
  })
  1. 完整示例代码:
@Entry
@Component
struct AnimationExample {
  @State scale: number = 1;
  @State opacity: number = 1;
  @State angle: number = 0;
  @State translateX: number = 0;
  @State isExpanded: boolean = false;

  build() {
    Column({ space: 20 }) {
      // animateTo 缩放动画
      Button('缩放动画')
        .scale({ x: this.scale, y: this.scale })
        .onClick(() => {
          animateTo({
            duration: 300,
            curve: Curve.EaseInOut,
            onFinish: () => console.info('Animation finished')
          }, () => {
            this.scale = this.scale === 1 ? 1.5 : 1;
          });
        })

      // .animation 透明度动画
      Button('透明度动画')
        .opacity(this.opacity)
        .animation({ duration: 500, curve: Curve.Linear })
        .onClick(() => {
          this.opacity = this.opacity === 1 ? 0.3 : 1;
        })

      // 旋转动画
      Image($r('app.media.icon'))
        .width(60)
        .height(60)
        .rotate({ angle: this.angle })
        .onClick(() => {
          animateTo({ duration: 500, curve: Curve.EaseOut }, () => {
            this.angle += 360;
          });
        })

      // 位移动画
      Text('滑动我')
        .padding(12)
        .backgroundColor('#007AFF')
        .fontColor(Color.White)
        .borderRadius(8)
        .translate({ x: this.translateX })
        .animation({ duration: 300, curve: Curve.Spring })
        .onClick(() => {
          this.translateX = this.translateX === 0 ? 100 : 0;
        })

      // 展开/收起动画
      Column() {
        Row() {
          Text('点击展开')
          Blank()
          Image($r('app.media.arrow'))
            .width(16)
            .rotate({ angle: this.isExpanded ? 90 : 0 })
            .animation({ duration: 200 })
        }
        .width('100%')
        .padding(12)
        .onClick(() => {
          animateTo({ duration: 300 }, () => {
            this.isExpanded = !this.isExpanded;
          });
        })

        if (this.isExpanded) {
          Text('展开的内容')
            .padding(12)
        }
      }
      .backgroundColor('#F5F5F5')
      .borderRadius(8)
    }
    .width('100%')
    .padding(20)
  }
}

更多关于HarmonyOS鸿蒙Next中如何使用animateTo和.animation实现UI动画效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用animateTo.animation实现UI动画的方法如下:

animateTo:用于触发显式动画。将状态变量变化包裹在animateTo闭包内,系统会自动生成过渡动画。 示例:

animateTo({ duration: 1000 }, () => {
  this.widthSize = 200
})

.animation:作为属性修饰器,为组件绑定隐式动画。当修饰的状态变量变化时,组件会自动产生动画效果。 示例:

@State widthSize: number = 100
...
.width(this.widthSize)
.animation({ duration: 1000 })

两者区别:animateTo主动触发动画块;.animation自动响应状态变化。

在HarmonyOS Next中,animateTo.animation是两种核心的UI动画实现方式,下面针对你的问题逐一解答。

1. animateTo() 显式动画

animateTo用于触发一组状态属性的显式动画。它通过闭包内的状态变化驱动动画。

基本语法与参数设置:

// 引入动画库
import { Curve, animateTo } from '@kit.ArkUI';

// 定义状态变量
@State myWidth: number = 100;
@State myOpacity: number = 1.0;

// 触发动画
animateTo({
  duration: 1000,      // 动画时长,单位ms
  curve: Curve.EaseIn, // 动画曲线
  delay: 200,          // 延迟开始,单位ms
  iterations: 1,       // 播放次数,-1表示无限
  playMode: PlayMode.Normal // 播放模式
}, () => {
  // 闭包内修改状态,变化将产生动画
  this.myWidth = 200;
  this.myOpacity = 0.5;
})

2. .animation() 属性动画

.animation是属性方法,直接附加到支持动画的属性上,当该属性值变化时自动产生动画。

与animateTo的主要区别:

  • 触发方式.animation是声明式的,属性变化自动触发;animateTo是命令式的,需主动调用。
  • 作用范围.animation仅作用于单个属性;animateTo可同步动画化闭包内的多个状态变化。
  • 控制粒度animateTo对一组动画的开始、结束有更强控制力。

.animation() 示例:

@State scale: number = 1;

// 当scale值变化时,自动应用动画效果
Image($r('app.media.icon'))
  .scale({ x: this.scale, y: this.scale })
  .animation({
    duration: 500,
    curve: Curve.Spring
  })

3. 常用动画效果实现

位移:

@State translateX: number = 0;

// 使用animateTo
animateTo({ duration: 300 }, () => {
  this.translateX = 100;
})

// 在组件上应用
Column()
  .translate({ x: this.translateX })

缩放:

@State scaleValue: number = 1;

// 使用.animation
Image($r('app.media.icon'))
  .scale({ x: this.scaleValue, y: this.scaleValue })
  .animation({ duration: 400, curve: Curve.EaseOut })

旋转:

@State angle: number = 0;

// 旋转动画
Column()
  .rotate({ x: 0, y: 0, z: 1, angle: this.angle })
  .animation({
    duration: 1000,
    curve: Curve.Linear,
    iterations: -1 // 无限旋转
  })

透明度:

@State opacityValue: number = 1.0;

// 淡入淡出
Text('Hello')
  .opacity(this.opacityValue)
  .animation({ duration: 500 })

4. 常用动画曲线

  • Curve.Linear:线性匀速
  • Curve.Ease:标准缓动(先加速后减速)
  • Curve.EaseIn:缓入(先慢后快)
  • Curve.EaseOut:缓出(先快后慢)
  • Curve.EaseInOut:缓入缓出
  • Curve.Spring:弹簧效果,有回弹
  • Curve.Friction:摩擦效果,逐渐停止

5. 组件出现/消失过渡动画

使用条件渲染结合状态动画:

@State isVisible: boolean = false;

// 控制组件显隐
if (this.isVisible) {
  Column()
    .opacity(this.isVisible ? 1 : 0) // 透明度过渡
    .scale({ x: this.isVisible ? 1 : 0.8, y: this.isVisible ? 1 : 0.8 }) // 缩放过渡
    .animation({ duration: 300, curve: Curve.EaseInOut })
}

// 切换显示状态
toggleVisibility() {
  animateTo({ duration: 300 }, () => {
    this.isVisible = !this.isVisible;
  })
}

综合示例:按钮点击动画

@State btnScale: number = 1;
@State btnOpacity: number = 1;

Button('点击我')
  .scale({ x: this.btnScale, y: this.btnScale })
  .opacity(this.btnOpacity)
  .onClick(() => {
    // 点击时先快速缩小再恢复
    animateTo({ duration: 100, curve: Curve.EaseOut }, () => {
      this.btnScale = 0.9;
    })
    animateTo({ duration: 200, delay: 100, curve: Curve.Spring }, () => {
      this.btnScale = 1;
    })
  })

以上示例展示了HarmonyOS Next中动画的基本用法。实际开发中可根据需求组合使用,animateTo适合复杂动画序列,.animation适合简单属性过渡。

回到顶部