HarmonyOS 鸿蒙Next中animateTo显式动画与属性动画

HarmonyOS 鸿蒙Next中animateTo显式动画与属性动画 ArkUI 提供了哪些动画能力?animateTo 显式动画和 .animation() 属性动画有什么区别?如何实现复杂的组合动画?如何控制动画的播放、暂停和取消?(问题来源项目案例整理:https://github.com/heqiyuan35-creator/HydroQuiz.git

3 回复

ArkUI 提供了丰富的动画能力,包括显式动画、属性动画、转场动画等。

animateTo 显式动画

@State scale: number = 1;
@State opacity: number = 1;
@State rotateAngle: number = 0;

// 基础动画
private playAnimation(): void {
  animateTo({
    duration: 300,
    curve: Curve.EaseOut,
    onFinish: () => console.log('动画完成')
  }, () => {
    this.scale = 1.2;
    this.opacity = 0.8;
  });
}

// 弹跳动画
private playBounceAnimation(): void {
  // 第一阶段:放大
  animateTo({ duration: 100, curve: Curve.EaseOut }, () => {
    this.scale = 0.9;
  });
  // 第二阶段:回弹
  setTimeout(() => {
    animateTo({ duration: 200, curve: Curve.EaseOut }, () => {
      this.scale = 1.1;
    });
  }, 100);
  // 第三阶段:恢复
  setTimeout(() => {
    animateTo({ duration: 150, curve: Curve.EaseInOut }, () => {
      this.scale = 1;
    });
  }, 300);
}

// 循环动画
private playLoopAnimation(): void {
  animateTo({
    duration: 1000,
    curve: Curve.Linear,
    iterations: -1,  // 无限循环
    playMode: PlayMode.Alternate  // 往返播放
  }, () => {
    this.rotateAngle = 360;
  });
}

属性动画 .animation()

Column() {
  Image($r('app.media.icon'))
    .width(100)
    .height(100)
    .scale({ x: this.scale, y: this.scale })
    .opacity(this.opacity)
    // 属性动画:当 scale 或 opacity 变化时自动执行动画
    .animation({
      duration: 300,
      curve: Curve.EaseOut
    })
}

区别

  • animateTo:主动触发,可以同时改变多个状态
  • .animation():被动触发,当绑定的属性变化时自动执行

更多关于HarmonyOS 鸿蒙Next中animateTo显式动画与属性动画的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS Next的animateTo显式动画通过闭包内修改状态变量驱动动画,支持自定义时长、曲线和延迟。属性动画通过animation属性直接绑定组件样式变化,如位置、透明度等,支持并行或串行组合。两者均基于ArkTS声明式语法,animateTo更适用于复杂动画序列,属性动画适合简单样式过渡。

在HarmonyOS Next的ArkUI中,动画能力主要分为两类:属性动画显式动画。你提到的animateTo.animation()正是这两类的核心代表。

核心区别:声明式 vs 命令式

  1. .animation() 属性动画

    • 类型:声明式动画。
    • 机制:通过修饰器(如.animation)直接绑定在组件的样式属性上。当状态变量(@State, @Prop, @Link等)发生变化时,ArkUI框架会自动计算新旧值的差异,并驱动属性按照指定的动画参数(时长、曲线、延迟等)过渡到新值。
    • 特点声明式、数据驱动。开发者只需关心状态的终态,动画过程由框架自动完成。适合对单一属性或一组属性进行简单的状态过渡。
    // 示例:当isEnlarged状态改变时,组件的尺寸和透明度会以动画方式过渡
    @State isEnlarged: boolean = false;
    ...
    Component()
        .width(this.isEnlarged ? 200 : 100)
        .height(this.isEnlarged ? 200 : 100)
        .opacity(this.isEnlarged ? 1.0 : 0.5)
        // 应用属性动画
        .animation({
            duration: 500,
            curve: Curve.EaseInOut
        })
        .onClick(() => {
            this.isEnlarged = !this.isEnlarged; // 状态改变触发动画
        })
    
  2. animateTo 显式动画

    • 类型:命令式动画。
    • 机制:在一个animateTo函数闭包内,同步地改变状态变量的值。框架会识别闭包内所有因状态变化而需要更新的UI属性,并将这些更新作为一个动画帧来执行。
    • 特点命令式、批量控制。它提供了一种“动画上下文”,在这个上下文中集中执行状态变更,从而确保多个属性的变化在同一动画周期内协同进行。这是实现复杂组合动画连续动画的关键。
    // 示例:点击后,同时(或顺序)执行多个属性的复杂变化
    @State myWidth: number = 100;
    @State myHeight: number = 100;
    @State myColor: Color = Color.Blue;
    ...
    async performComplexAnimation() {
        // 第一个动画阶段:放大并变色
        animateTo({
            duration: 300,
            curve: Curve.EaseIn
        }, () => {
            this.myWidth = 200;
            this.myHeight = 200;
            this.myColor = Color.Red;
        });
    
        // 等待第一阶段完成
        await new Promise(resolve => setTimeout(resolve, 300));
    
        // 第二个动画阶段:移动位置
        animateTo({
            duration: 500,
            curve: Curve.Spring
        }, () => {
            this.myWidth = 150;
            this.myHeight = 150;
            // 可以结合其他状态变量控制位置等
        });
    }
    

如何实现复杂的组合动画?

主要依靠animateTo

  • 同一动画周期内的组合:在单个animateTo闭包内修改多个状态变量,这些变量的变化将共享同一动画参数(时长、曲线),形成严格的同步组合动画。
  • 连续动画序列:通过async/await或Promise链,顺序调用多个animateTo,可以创建复杂的多阶段动画序列(如先放大、再移动、然后旋转)。
  • 与属性动画结合:在animateTo闭包内改变的状态,如果其对应的组件属性也使用了.animation()修饰器,则animateTo的参数将覆盖.animation()的参数,实现更灵活的控制。

如何控制动画的播放、暂停和取消?

在HarmonyOS Next的ArkUI中,动画的控制主要依赖于对状态动画执行流程的管理,而非直接的操作句柄。

  • 播放:触发状态变化。对于属性动画,直接改变绑定的状态变量;对于显式动画,调用包含animateTo的函数。
  • 暂停:ArkUI框架没有提供直接的动画暂停API。常见的变通方案是使用离散值动画(如关键帧动画)或通过控制动画时长和曲线来模拟“定格”效果。更精细的控制通常需要借助Canvas等自绘组件实现。
  • 取消/中断
    • 属性动画:在动画执行过程中,再次改变状态变量,动画会立即中断当前过渡,并开始向新的目标值过渡。
    • 显式动画animateTo本身是同步代码块。要取消一个正在执行的动画序列,需要在逻辑层进行控制,例如设置一个“取消标志位”,在下一个animateTo或状态变更前进行检查并跳过后续动画逻辑。

总结

  • 使用 .animation() 实现简单的、数据驱动的属性过渡。
  • 使用 animateTo 实现复杂的、多属性协同的或连续的组合动画。
  • 动画的播放由状态驱动暂停功能有限取消通过中断状态变更来实现。

在你的HydroQuiz项目中,可以根据交互场景选择:

  • 按钮状态切换、简单出现消失效果,用属性动画更简洁。
  • 复杂的答题反馈动画、连续的游戏过程动画,用显式动画animateTo)更容易构建和控制时序。
回到顶部