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第一课:官方认证培训

🔗 完整代码仓库

相关推荐
wangxiaowu19864 小时前
HarmonyOS NEXT和通用JSBridge
华为·harmonyos
l1340620823513 小时前
Flutter Geocoding 在鸿蒙上的使用指南
flutter·华为·harmonyos
俩毛豆13 小时前
【毛豆工具集】【UI】【多设备适配】实现与屏幕密度等倍的图片加载
华为·harmonyos
l1340620823514 小时前
344.在鸿蒙上使用 animations Flutter 包的指南
flutter·华为·harmonyos
灯前目力虽非昔,犹课蝇头二万言。14 小时前
HarmonyOS笔记12:生命周期
笔记·华为·harmonyos
Random_index16 小时前
#HarmonyOS篇:学习UI规范基本语法&&学习UI范式装填管理V1&&学习UI范式装填管理V2&&学习UI范式渲染控制
harmonyos
前端世界16 小时前
鸿蒙分布式权限管理实战指南:架构原理 + 可运行 Demo
分布式·架构·harmonyos
前端世界17 小时前
鸿蒙分布式通信安全实践:中间人攻击原理与防御实现
分布式·华为·harmonyos
kirk_wang17 小时前
Flutter 三方库 simple_circular_progress_bar 在 OHOS 平台的适配实践
flutter·移动开发·跨平台·arkts·鸿蒙
1 天前
鸿蒙——通知
华为·harmonyos·