HarmonyOS5 极致动效实验室:基本动画的使用

大家好,我是不想掉发的鸿蒙开发工程师城中的雾,本期将为大家分享HarmonyOS动画相关的系列内容,我将使用动画的基本使用以及高阶的粒子动画的例子来将

不管是HarmonyOS还是Android、IOS的应用开发中,动效(Animation)是提升用户体验、增强界面流畅度的重要一环。鸿蒙的ArkUI 提供了丰富的动画能力,从最基础的属性动画到转场动画,都能通过声明式的方式来实现。

本期文章作为《HarmonyOS 极致动效实验室》系列的第一篇,我们将基于最新的 @ComponentV2 状态管理范式,通过四个典型的实战场景:属性动画 (animation)、显式动画 (animateTo)、帧动画 (Animator)以及列表转场动画 (Transition),结合实例解析 ArkUI 中几种核心动画接口的使用方法及适用场景。

1. 动效的核心逻辑

在 ArkUI 的声明式开发范式中,驱动动画的核心逻辑非常简单:状态(State)驱动 UI 变化

我们无需关注每一帧的绘制逻辑,只需要改变状态变量(如 widthopacity 等),并通过动画接口告诉系统"这段变化需要通过动画过渡",系统便会自动根据指定的曲线(Curve)和时长(Duration)进行插值计算

2. 属性动画 (animation)

这是最常用、最简洁的动画实现方式。它通过 .animation() 接口绑定到组件的属性链上,当组件的布局属性发生变化时,系统会自动添加过渡效果。

场景一:交互式变形按钮

实现一个点击后宽度变长、圆角变小的加载按钮。

(核心代码片段)

复制代码
@ComponentV2
struct ImplicitDemo {
  @Local isExpanded: boolean = false;

  build() {
    Column() {
      Row() {
         if (this.isExpanded) {
           Text("正在加载资源...")
             .fontColor(Color.White)
             .transition(TransitionEffect.OPACITY.animation({ duration: 300 }))
         } else {
           Text("Go").fontColor(Color.White)
         }
      }
      // 1. 布局属性与状态绑定
      .width(this.isExpanded ? 220 : 60)
      .height(60)
      .borderRadius(this.isExpanded ? 12 : 30)
      .backgroundColor('#007DFF')
      .justifyContent(FlexAlign.Center)
      
      // 2. animation 接口:监听上方属性的变化
      .animation({
        duration: 500,
        curve: Curve.FastOutSlowIn // 推荐使用 FastOutSlowIn 曲线,增强跟手感
      })
      
      .onClick(() => {
        // 3. 修改状态触发动画
        this.isExpanded = !this.isExpanded;
      })
    }
  }
}

性能优化建议:

在复杂布局中,频繁修改 width 或 height 可能会触发组件的重排(Relayout),消耗较多性能。如果只是单纯的视觉缩放,建议优先使用 .scale() 或 .translate() 属性,因为它们主要在渲染层处理,性能更优。

3. 显式动画 (animateTo)

当我们需要在业务逻辑中精准控制动画的触发时机,或者需要一次性驱动多个组件协同变化时,显式动画 animateTo 是更好的选择。

场景二:侧边栏抽屉效果

点击按钮,遮罩层渐显,同时侧边栏从左侧滑出。

复制代码
@ComponentV2
struct DrawerDemo {
  @Local showDrawer: boolean = false;

  build() {
    Stack({ alignContent: Alignment.Start }) {
      // 主内容区
      Column() {
        Button("打开菜单")
          .onClick(() => {
            // 使用 animateTo 包裹状态修改逻辑
            animateTo({ duration: 300, curve: Curve.EaseOut }, () => {
              this.showDrawer = true;
            })
          })
      }

      // 遮罩层
      if (this.showDrawer) {
        Column()
          .backgroundColor('rgba(0,0,0,0.5)')
          .transition(TransitionEffect.OPACITY.animation({ duration: 300 }))
          .onClick(() => {
             // 关闭抽屉
             animateTo({ duration: 300, curve: Curve.EaseIn }, () => {
               this.showDrawer = false;
             })
          })
      }
      
      // 侧边栏
      Column() { /* 菜单内容 */ }
      .translate({ x: this.showDrawer ? '0%' : '-100%' }) // 使用位移控制进出
    }
  }
}

4. 帧动画 (Animator)

对于非 UI 布局属性的动画(例如数字滚动、Canvas 绘图参数变化),标准的 .animation 接口无法直接支持。在 HarmonyOS 中,我们需要通过 getUIContext().createAnimator 来创建帧动画对象,实现逐帧控制。

场景三:数字滚动效果

实现账户余额从当前值平滑滚动到目标值的效果。

关键点 :使用 getUIContext().createAnimator 获取当前 UI 上下文的动画引擎,确保 VSync 同步。

复制代码
import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';

@ComponentV2
struct NumberTicker {
  @Local currentNum: number = 0;
  private _animator: AnimatorResult | undefined = undefined;

  // 封装动画执行逻辑
  runAnimatorTo(target: number) {
    if (this._animator) {
      this._animator.cancel();
    }

    let options: AnimatorOptions = {
      duration: 2000,
      easing: "ease",
      begin: this.currentNum, // 从当前值开始
      end: target,            // 明确终点,防止误差
      fill: "forwards"
    };

    // 获取当前 UI 上下文并创建 Animator
    this._animator = this.getUIContext().createAnimator(options);

    this._animator.onFrame = (value: number) => {
      this.currentNum = value; // 更新状态,驱动 UI 刷新
    };

    this._animator.play();
  }
}

5. 列表转场动画 (Transition)

在列表数据发生增删时,如果没有动画过渡,界面会显得非常生硬。ArkUI 提供了 TransitionEffect 来专门处理组件的挂载(Appear)和卸载(Disappear)动画。

场景四:列表项动态增删

复制代码
@ComponentV2
struct ListAnimationDemo {
  @Local listData: number[] = [1, 2, 3];

  build() {
    List({ space: 10 }) {
      ForEach(this.listData, (item: number) => {
        ListItem() {
           // ... 列表项内容
        }
        // 定义转场效果:组合了透明度、位移和缩放
        .transition(
          TransitionEffect.OPACITY
            .combine(TransitionEffect.translate({ y: 20 }))
            .combine(TransitionEffect.scale({ x: 0.8, y: 0.8 }))
        )
      }, (item: number) => JSON.stringify(item))
    }
  }
  
  // 注意:修改数组的操作需要在 animateTo 中进行
  addItem() {
    animateTo({ duration: 300, curve: Curve.EaseOut }, () => {
      this.listData.push(this.nextId++);
    })
  }
}

总结

在实际开发中,我们应根据具体需求选择合适的动画方案:

  1. 属性动画 (.animation):适用于简单的组件属性变化,代码最简洁。
  2. 显式动画 (animateTo):适用于需要精确控制时序或多组件联动的场景。
  3. 帧动画 (Animator):适用于自定义数值计算或 Canvas 绘图等非布局属性动画。
  4. 组件转场 (transition):专用于处理组件的显示与消失(增删)。

希望本期的内容能为大家在鸿蒙动效开发上提供一些参考。后续我们将深入探讨更高级的共享元素转场 (geometryTransition) 技术,敬请关注。

充电时间

如果您想系统深入地学习 HarmonyOS 开发或想考取HarmonyOS认证证书,欢迎加入华为开发者学堂:

🔗 HarmonyOS第一课:官方认证培训

monyOS 开发或想考取HarmonyOS认证证书,欢迎加入华为开发者学堂:

🔗 HarmonyOS第一课:官方认证培训

🔗 完整代码仓库

相关推荐
晚霞的不甘3 小时前
鸿蒙(HarmonyOS)UI 美化实战:打造美观、响应式的应用界面
ui·华为·harmonyos
晚霞的不甘3 小时前
鸿蒙(HarmonyOS)应用开发深度入门:ArkTS 语法、UI 构建与状态管理详解
ui·华为·harmonyos
花先锋队长3 小时前
升级鸿蒙6,华为Mate 70 Air智感握姿适配,接电话按键会“找手”了
华为·harmonyos
遇到困难睡大觉哈哈3 小时前
HarmonyOS收银台设计规范:构建简洁高效的支付体验
华为·harmonyos·设计规范
kirk_wang3 小时前
Flutter Printing库在OpenHarmony上的适配实战
flutter·移动开发·跨平台·arkts·鸿蒙
晚霞的不甘4 小时前
[鸿蒙2025领航者闯关]Flutter + OpenHarmony 安全开发实践:构建可信、合规、防逆向的鸿蒙应用
安全·flutter·harmonyos
晚霞的不甘4 小时前
[鸿蒙2025领航者闯关]Flutter + OpenHarmony 性能调优实战:打造 60fps 流畅体验与低功耗的鸿蒙应用
flutter·华为·harmonyos
解局易否结局4 小时前
UI+Widget:鸿蒙/Flutter等声明式UI框架的核心设计范式深度解析
flutter·ui·harmonyos
白茶三许13 小时前
【江鸟中原】“策无忧” 决策模型纯血鸿蒙项目开发
华为·harmonyos