【HarmonyOS开发小实践】ArkUI 动画系统属性动画、显式动画与路径动画

ArkUI 动画系统属性动画、显式动画与路径动画

动画让界面"活"起来

静态界面能用,但缺了动画的过渡会显得生硬。ArkUI 提供了从简单到复杂的动画能力:属性动画、显式动画、路径动画,以及组件内置动画。这篇把常用动画类型讲清楚。

属性动画:给属性加动画

属性动画是最简单的动画方式------某个属性值变化时,自动生成过渡动画,而不是瞬间跳变。

typescript 复制代码
@Entry
@Component
struct AttributeAnimationDemo {
  @State size: number = 100;

  build() {
    Column({ space: 20 }) {
      // 一个会变大变小的方块
      Text('')
        .width(this.size)
        .height(this.size)
        .backgroundColor('#FF6B35')
        .animation({  // 属性动画
          duration: 300,  // 时长 300ms
          curve: Curve.EaseInOut  // 缓动曲线
        })

      Button('变大')
        .onClick(() => {
          this.size = 200;  // 改属性,动画自动过渡
        })
      Button('变小')
        .onClick(() => {
          this.size = 100;
        })
    }
  }
}

.animation() 给这个组件的属性变化统一加动画。改 size 时,宽高不再是瞬间跳到 200,而是 300ms 内平滑过渡。

多属性组合动画

.animation() 一次只管一个组件的动画参数,但可以给多个属性加 animation,或指定动画哪些属性:

typescript 复制代码
Text('')
  .width(this.size)
  .height(this.size)
  .backgroundColor(this.color)
  .borderRadius(this.radius)
  .animation({ duration: 300, curve: Curve.EaseInOut })  // 所有动画属性统一动画

上面 size、color、radius 变化都会过渡。如果想对不同属性用不同动画,可以分别设置。

缓动曲线 Curve

缓动曲线决定了动画速度的变化方式,直接影响动画手感:

曲线 特点 适用
Curve.Linear 匀速 进度条、循环动画
Curve.EaseIn 慢进快出 元素消失、退出
Curve.EaseOut 快进慢出 元素出现、进入
Curve.EaseInOut 慢进慢出 大多数过渡
Curve.Friction 摩擦减速 模拟物理惯性

App 里的常规过渡用 EaseInOut,进入动画用 EaseOut(快进慢出更自然),退出用 EaseIn。

显式动画:更精细的控制

属性动画是"改属性自动动",显式动画是"主动调 API 触发动画"。显式动画能控制更多细节:

typescript 复制代码
@Entry
@Component
struct ExplicitAnimationDemo {
  @State width: number = 100;

  build() {
    Column({ space: 20 }) {
      Text('')
        .width(this.width)
        .height(100)
        .backgroundColor('#4A90E2')

      Button('显式动画展开')
        .onClick(() => {
          // 显式动画:包住要动画的状态修改
          this.getUIContext().animateTo({
            duration: 500,
            curve: Curve.EaseInOut,
            iterations: 1,  // 播放次数
            playMode: PlayMode.Normal
          }, () => {
            // 闭包里改状态,触发动画
            this.width = 300;
          });
        })
    }
  }
}

animateTo 的第一个参数是动画配置,第二个参数是回调,回调里的状态修改会被动画化。显式动画的优点:

  • 能控制 iterations(次数)、playMode(播放模式)
  • 能把多个状态修改放在一个闭包里,统一做动画

显式动画 vs 属性动画

复制代码
属性动画:改属性 → 自动动(简单,适合固定动画)
显式动画:调 API → 闭包改状态 → 动画(灵活,适合复杂控制)

选型:
  普通 hover、尺寸变化 → 属性动画 .animation()
  需要控制次数/方向/多状态联动 → 显式动画 animateTo()

路径动画:沿轨迹运动

属性动画只能做值的变化(大小、颜色、透明度),路径动画让元素沿指定的轨迹运动:

typescript 复制代码
@Entry
@Component
struct PathAnimationDemo {
  @State offsetX: number = 0;
  @State offsetY: number = 0;

  build() {
    Stack() {
      // 沿圆形轨迹运动的小球
      Circle()
        .width(30)
        .height(30)
        .fill('#FF6B35')
        .offset({ x: this.offsetX, y: this.offsetY })
        .animation({ duration: 2000, curve: Curve.Linear })
    }
    .onClick(() => {
      // 圆周运动:通过三角函数更新位置
      let angle = 0;
      let timer = setInterval(() => {
        angle += 0.1;
        this.offsetX = 150 * Math.cos(angle);  // x = r·cos(θ)
        this.offsetY = 150 * Math.sin(angle);  // y = r·sin(θ)
        if (angle >= Math.PI * 2) {
          clearInterval(timer);
        }
      }, 50);
    })
  }
}

路径动画本质是"按时间轴手动更新位置,配合属性动画做平滑过渡"。复杂路径(贝塞尔曲线、抛物线)都是这个思路------用数学公式算出每一帧的位置。

转场动画动画的完整案例

用属性动画 + 缓动曲线做一个"侧滑菜单":

typescript 复制代码
@Entry
@Component
struct SlideMenuDemo {
  @State isOpen: boolean = false;
  @State menuOffset: number = -250;  // 菜单默认藏在左侧

  build() {
    Stack({ alignContent: Alignment.Start }) {
      // 主内容
      Column() {
        Text('主内容区')
        Button('打开菜单')
          .onClick(() => {
            this.isOpen = !this.isOpen;
            this.menuOffset = this.isOpen ? 0 : -250;
          })
      }
      .width('100%')
      .height('100%')

      // 侧滑菜单
      Column() {
        Text('菜单项 1')
        Text('菜单项 2')
        Text('菜单项 3')
      }
      .width(250)
      .height('100%')
      .backgroundColor('#333333')
      .offset({ x: this.menuOffset })
      .animation({ duration: 300, curve: Curve.EaseInOut })  // 平滑滑入滑出
    }
  }
}

菜单的 offset 在 -250 和 0 之间切换,.animation() 让它平滑滑动,300ms 的 EaseInOut 手感刚好。

动画的几条经验

  1. 时长别太长。界面过渡动画 200-400ms 合适,超过 500ms 会让人感觉"卡"。加载动画可以循环,但转场要快。

  2. 缓动曲线比时长更影响手感 。同样的 300ms,Linear 生硬,EaseInOut 自然。默认 EaseInOut 是安全选择。

  3. 能属性动画就别显式动画 。属性动画代码更简洁,只有需要控制次数、方向、多状态联动时才用 animateTo。

  4. 避免动画里做重计算。动画回调(尤其是路径动画的 timer)里别做昂贵操作,否则掉帧。

  5. 列表项动画要节制。长列表里每项都做复杂动画会影响滚动性能,列表动画优先用组件内置的轻量动效。

相关推荐
aqi0011 小时前
鸿蒙版本的电子书阅读APP开放源码啦
android·华为·ai编程·harmonyos·鸿蒙
xq952715 小时前
HDC Assistant 插件横空出世
harmonyos
余槐i18 小时前
200万行表加索引锁死写入:PostgreSQL CONCURRENTLY 的三类等待与重建路径
数据库·postgresql·性能优化·索引·explain
兰亭妙微UI设计公司19 小时前
兰亭妙微界面设计公司分享:如何高效改善设计质量|实战分析
ui
打工仔折腾 AI21 小时前
FaceFusion本地换脸实战:Windows整合包、模型选择与遮罩调参记录
人工智能·windows·后端·python·深度学习·性能优化·ai agent 实战
且随疾风前行.1 天前
UI核心 - 绘制流程(测量、布局、绘制)
ui·dubbo
@#¥&~是乱码鱼啦1 天前
ArkWeb 混合手记 07|性能优化、内存管控、内核预热、崩溃防护,整套系列终章
性能优化
lvqinglou1 天前
学习Sql-part1 for婷姐
sql·学习·性能优化
JMchen1 天前
性能优化——让Native代码飞起来
android·c++·性能优化
OH_TPC1 天前
【鸿蒙优选三方库】@ohos/aki:一行代码让 ArkTS 调 C++
harmonyos