HarmonyOS 鸿蒙Next中转场动画与页面切换效果

HarmonyOS 鸿蒙Next中转场动画与页面切换效果 如何在 ArkUI 中实现页面切换的转场动画?如何自定义组件的出现和消失动画?如何实现共享元素转场?如何处理转场动画中的手势交互?(问题来源项目案例整理: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中转场动画与页面切换效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙Next中转场动画与页面切换效果基于ArkUI框架实现。支持共享元素转场、页面转场和组件内转场,通过transition属性配置。常用动画类型包括平移、旋转、缩放和透明度变化。页面切换可通过router模块的push和pop方法触发转场动画。开发者可自定义动画参数如duration和curve,实现平滑过渡效果。

在HarmonyOS Next的ArkUI中,实现页面切换与组件动画主要依赖声明式UI的动画API和转场机制。以下是针对您问题的具体实现方案:

1. 页面切换转场动画

使用Navigation组件时,可通过pageTransition函数为页面配置进入/退出动画:

// 页面级转场
@Entry
@Component
struct PageTransitionExample {
  build() {
    Navigation() {
      PageTransitionPage({ title: 'PageA' })
    }
  }
}

@Component
struct PageTransitionPage {
  build() {
    Column() {
      // 页面内容
    }
    .pageTransition({
      // 进入动画
      slide: SlideEffect.Right,
      // 退出动画  
      opacity: 0.5
    })
  }
}

2. 组件出现/消失动画

使用transitionanimateTo实现组件级动画:

@Component
struct ComponentAnimation {
  @State isVisible: boolean = true;
  @State opacityVal: number = 1;

  build() {
    Column() {
      if (this.isVisible) {
        Text('出现/消失动画')
          .transition({ type: TransitionType.Insert, scale: { x: 0, y: 0 } })
          .transition({ type: TransitionType.Delete, opacity: 0 })
      }
      
      Button('切换显示')
        .onClick(() => {
          animateTo({
            duration: 500,
            curve: Curve.EaseInOut
          }, () => {
            this.isVisible = !this.isVisible;
            this.opacityVal = this.isVisible ? 1 : 0;
          })
        })
    }
  }
}

3. 共享元素转场

通过sharedTransition实现元素在页面间平滑过渡:

// 页面A
@Component
struct PageA {
  build() {
    Navigation() {
      Column() {
        Image($r('app.media.icon'))
          .sharedTransition('sharedImage', {
            duration: 300,
            curve: Curve.Friction
          })
          .onClick(() => {
            router.pushUrl({ url: 'pages/PageB' });
          })
      }
    }
  }
}

// 页面B  
@Component
struct PageB {
  build() {
    Column() {
      Image($r('app.media.icon'))
        .sharedTransition('sharedImage') // 相同ID实现共享
    }
  }
}

4. 手势交互转场

结合PanGesture和动画API实现手势驱动转场:

@Component
struct GestureTransition {
  @State offsetX: number = 0;
  @State isExiting: boolean = false;
  private panGesture: PanGesture = new PanGesture();

  build() {
    Column() {
      // 可拖拽内容区域
    }
    .gesture(
      this.panGesture
        .onActionStart(() => {
          // 手势开始
        })
        .onActionUpdate((event: GestureEvent) => {
          // 更新位置
          this.offsetX = event.offsetX;
        })
        .onActionEnd(() => {
          // 判断是否触发页面切换
          if (Math.abs(this.offsetX) > 100) {
            animateTo({
              duration: 200,
              curve: Curve.EaseOut
            }, () => {
              this.isExiting = true;
              // 执行路由跳转
              router.back();
            })
          }
        })
    )
    .translate({ x: this.offsetX })
  }
}

关键要点:

  • 转场类型:支持平移、缩放、旋转、透明度等多种效果
  • 动画曲线:提供Ease、Spring、Friction等预置曲线,支持自定义贝塞尔曲线
  • 性能优化:推荐使用animateTo的闭包批量更新状态,减少布局计算次数
  • 手势协调:通过gesture修饰符与转场动画结合,实现自然交互体验

这些API共同构成了ArkUI完整的转场动画体系,能够满足从简单页面切换到复杂手势交互动画的各类场景需求。

回到顶部