温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在OpenHarmony中添加动画效果

发布时间:2025-12-20 01:05:57 来源:亿速云 阅读:116 作者:小樊 栏目:软件技术

OpenHarmony添加动画效果的实用指南

一、动画类型与适用场景

  • 属性动画:组件属性变化(如 width、height、backgroundColor、opacity、scale、rotate、translate)时自动产生过渡效果,适合连续、细粒度的状态变化。
  • 显示动画 animateTo:显式地将一组状态变化包装成动画,常用于“从状态A到状态B”的过渡,并可统一配置时长、曲线、延时等。
  • 转场动画 transition:用于组件插入/删除时的过渡,性能优于用 animateTo 在回调里做条件切换;可配合 id 使转场可打断。
  • 页面间转场 pageTransition:配置页面入场/退场的自定义转场动效。
  • 共享元素转场:页面间共享元素的平滑过渡。
  • 路径动画:让组件沿指定路径运动。
  • 窗口动画:应用启动/退出时窗口与控件的联动动画。

二、快速上手三步法

  • 步骤1 选择动画方式
    • 仅属性变化:优先用属性动画(如 .animation({…}))。
    • 多属性联动或需要统一配置:用 animateTo
    • 组件显隐:优先 transition
  • 步骤2 配置关键参数
    • duration(毫秒)、curve(如 Curve.EaseOut、Curve.FrictioncubicBezier)、delayiterations(-1 为无限)、playMode(如 PlayMode.AlternateReverse)。
  • 步骤3 绑定触发时机
    • 自动播放:在组件的 .onAppear(() => { … }) 中启动。
    • 交互播放:在 onClick 等事件中启动。

三、代码示例

  • 示例1 属性动画 + 显式动画 animateTo(按钮尺寸与旋转)
import { Curves } from '@ohos.curves';
import { animateTo, Curve, PlayMode } from '@ohos.animation';

@Entry
@Component
struct AnimateToExample {
  @State widthSize: number = 250;
  @State heightSize: number = 100;
  @State rotateAngle: number = 0;
  private flag: boolean = true;

  build() {
    Column({ space: 30 }) {
      Button('change width and height')
        .width(this.widthSize)
        .height(this.heightSize)
        .onClick(() => {
          if (this.flag) {
            animateTo({
              duration: 2000,
              curve: Curve.EaseOut,
              iterations: 3,
              playMode: PlayMode.Normal,
              onFinish: () => console.info('play end')
            }, () => {
              this.widthSize = 100;
              this.heightSize = 50;
            });
          } else {
            animateTo({}, () => {
              this.widthSize = 250;
              this.heightSize = 100;
            });
          }
          this.flag = !this.flag;
        });

      Button('change rotate angle')
        .rotate({ angle: this.rotateAngle })
        .onClick(() => {
          animateTo({
            duration: 1200,
            curve: Curve.Friction,
            delay: 500,
            iterations: -1, // 无限循环
            playMode: PlayMode.AlternateReverse,
            onFinish: () => console.info('play end')
          }, () => {
            this.rotateAngle = 90;
          });
        });
    }
    .width('100%')
    .margin({ top: 20 });
  }
}
  • 示例2 组件转场 transition(显隐淡入淡出)
import { TransitionEffect } from '@ohos.animation.transition';

@Entry
@Component
struct TransitionExample {
  @State show: boolean = true;

  build() {
    Column({ space: 20 }) {
      if (this.show) {
        Text('Hello, OpenHarmony')
          .id('myText') // 建议设置 id,便于打断/管理
          .fontSize(20)
          .backgroundColor('#007DFF')
          .fontColor(Color.White)
          .padding(10)
          .borderRadius(8)
          .transition(TransitionEffect.OPACITY.animation({ duration: 1000 }))
      }

      Button(this.show ? 'Hide' : 'Show')
        .onClick(() => {
          this.show = !this.show;
        })
    }
    .width('100%')
    .padding(20);
  }
}
  • 示例3 页面间转场 pageTransition(共享元素)
import { pageTransition, SharedTransitionEffect, SharedTransitionDirection } from '@ohos.animation.pageTransition';

@Entry
@Component
struct PageA {
  build() {
    Column() {
      Image($r('app.media.icon'))
        .width(80).height(80)
        .sharedTransition('icon', SharedTransitionEffect.SCALE, SharedTransitionDirection.BOTH)
        .onClick(() => {
          // 跳转到 PageB
        })
    }
    .width('100%').height('100%').justifyContent(FlexAlign.Center)
  }
}

@Entry
@Component
struct PageB {
  build() {
    Column() {
      Image($r('app.media.icon'))
        .width(160).height(160)
        .sharedTransition('icon', SharedTransitionEffect.SCALE, SharedTransitionDirection.BOTH)
    }
    .width('100%').height('100%').justifyContent(FlexAlign.Center)
  }
}
  • 示例4 启动页 Logo 渐显放大并跳转
import router from '@ohos.router';
import { animateTo, Curve } from '@ohos.animation';
import { Curves } from '@ohos.curves';

@Entry
@Component
struct Logo {
  @State opacityValue: number = 0;
  @State scaleValue: number = 0;
  private curve1 = Curves.cubicBezier(0.4, 0, 1, 1);

  build() {
    // 假设 Logo 使用 Image 或 Shape
    Image($r('app.media.logo'))
      .width(120).height(120)
      .opacity(this.opacityValue)
      .scale({ x: this.scaleValue, y: this.scaleValue })
      .onAppear(() => {
        animateTo({
          duration: 1000,
          curve: this.curve1,
          delay: 100,
          onFinish: () => {
            setTimeout(() => {
              router.replaceUrl({ url: 'pages/Main' }); // 跳转到主页
            }, 1000); // 动画定格 1s 后跳转
          }
        }, () => {
          this.opacityValue = 1;
          this.scaleValue = 1;
        });
      })
  }
}

以上示例覆盖了属性动画、显式动画、转场与页面间共享元素转场的常见用法,参数如 duration、curve、delay、iterations、playMode 可按需调整。

四、性能与最佳实践

  • 优先使用 transform(如 scale/rotate/translate)实现位移与形变,避免频繁改动 width/height/layoutWeight 等布局属性,减少重排开销。
  • 组件显隐优先用 transition,比在 animateToonFinish 里改条件更简洁且性能更好。
  • 多个属性需要一致动效时,尽量放入同一个 animateTo,减少动画调度开销。
  • 多次触发动画时,合并状态更新,避免冗余刷新与抖动。
  • 动画参数相同时复用同一动画配置;对长列表或复杂动效,控制并发与层级复杂度,必要时降低帧率或简化路径。

五、常见问题与排查

  • 动画不生效:确认属性是否支持动画(如 opacity、scale、rotate、translate 等),以及是否通过 animateToanimation({…}) 正确触发。
  • 转场无效:组件插入/删除场景优先用 transition;若需打断或精细化控制,给组件设置 id
  • 曲线/时长不生效:检查 animateTo 的配置是否覆盖到状态变更闭包;页面间动效需使用 pageTransitionsharedTransition
  • 循环与往返播放:使用 iterations: -1 实现无限循环,配合 playMode: PlayMode.AlternateReverse 往返播放。
  • 性能卡顿:避免动画过程中进行复杂计算或布局操作,减少重排与重绘,优先使用 GPU 加速属性。
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI