HarmonyOS鸿蒙Next中router跳转如何添加翻转的3D动画?

HarmonyOS鸿蒙Next中router跳转如何添加翻转的3D动画? router跳转到其他页面带有自右向左的180度3D翻转的动画效果如何实现?

4 回复

背景知识:

1、使用 Stack 简单做一个旋转:

  • animateTo:提供animateTo接口来指定由于闭包代码导致的状态变化插入过渡动效。
  • Stack:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
  • rotate:设置组件旋转。
  • zIndex:设置组件的堆叠顺序。

2、使用Swiper组件来做一个简单的3D旋转:

  • Swiper组件:滑块视图容器组件,它提供了子组件滑动轮播显示的能力。
  • customContentTransition属性:用于实现自定义的过渡动画效果,该属性允许开发者通过回调函数动态控制轮播切换过程中的动画细节,特别是可结合进度参数进行精细化动画控制。
  • rotate属性:主要用于设置组件的旋转,可使组件在以组件左上角为坐标原点的坐标系中进行旋转。

问题解决:

代码示例:

1、Stack 简单

@Entry
@Component
struct AnimationPage {
    @State angle: number = 0;
    @State zIndexNumber: number = 1;
    uiContext: UIContext | undefined = undefined;

    aboutToAppear(): void {
        this.uiContext = this.getUIContext()
    }

    build() {
        Column() {
            Row() {
                Button("切换背面")
                    .fontSize(20)
                    .fontColor(Color.White)
                    .fontWeight(FontWeight.Bold)
                    .backgroundColor(Color.Green)
                    .onClick(() => {
                        this.uiContext?.animateTo({ duration: 1000 }, () => {
                            this.angle = 180
                            this.zIndexNumber = -1
                        })
                    })

                Button("切换正面")
                    .fontSize(20)
                    .fontColor(Color.White)
                    .fontWeight(FontWeight.Bold)
                    .backgroundColor(Color.Green)
                    .onClick(() => {
                        this.uiContext?.animateTo({ duration: 2000 }, () => {
                            this.angle = 0;
                            this.zIndexNumber = 1
                        })
                    })
            }
            .width("100%")
            .justifyContent(FlexAlign.Center)


            Stack() {
                Column() {
                    Text('背面的内容')
                        .fontSize(50)
                }
                .backgroundColor(Color.Pink)
                .width('100%')
                .height('100%')
                .rotate({ y: 5, angle: 180 }) // 设置组件旋转轴向量坐标和旋转角度

                Column() {
                    Text('正面的内容')
                        .fontSize(50)
                }
                .backgroundColor('#ff709df8')
                .width('100%')
                .height('100%')
                .zIndex(this.zIndexNumber) // 根据zIndexNumber设置层级
            }
            .width("100%")
            .layoutWeight(1)
            .rotate({ y: 5, angle: this.angle, perspective: 2000 })

        }
        .height('100%')
        .width('100%')
    }
}

2、Swiper组件

@Entry
@Component
struct AnimationPage {
    uiContext: UIContext | undefined = undefined;

    // 旋转中心点列表
    @State centerXList: Array<number | string> = [];
    // 旋转角度列表
    @State angleList: number[] = [];

    colors:ResourceColor[] = [Color.Red,Color.Blue,Color.Green]

    aboutToAppear(): void {
        this.uiContext = this.getUIContext()
    }

    build() {
        Column() {
            Swiper() {
                ForEach(["11", "22", "33"],
                    (item: string, index: number) => {
                       Stack(){
                           Text(item)
                               .fontSize(20)
                               .fontColor(Color.Black)
                               .fontWeight(FontWeight.Bold)
                               .textAlign(TextAlign.Center)

                       }
                       .width("100%")
                       .height("100%")
                       .backgroundColor(this.colors[index])
                       .rotate({
                           x:0,
                           y:1,
                           z:0,
                           angle:this.angleList[index],
                           centerX:this.centerXList[index],
                           centerY:"50%",
                           centerZ:0,
                           perspective:0
                       })

                    },
                    (item: string, index: number) => JSON.stringify(item))
            }
            .width("100%")
            .height("100%")
            .customContentTransition({
                timeout:1000,
                transition:(proxy:SwiperContentTransitionProxy)=>{
                    // 旋转角度
                    let angle = 0;
                    console.info('proxy.position===>' + proxy.position);
                    console.info('proxy.index===>' + proxy.index);
                    // position为index页面相对于selectedIndex对应页面的起始位置的移动比例,向左移动减小,向右移动增加。
                    if (proxy.position < 0 && proxy.position > -1) {
                        // 当前页向左滑出或上一页向右滑入
                        angle = proxy.position * 90;
                        // 设置index页面的旋转中心轴为右侧边缘
                        this.centerXList[proxy.index] = '100%';
                    } else if (proxy.position > 0 && proxy.position < 1) {
                        // 当前页向右滑出或下一页向左滑入
                        angle = proxy.position * 90;
                        // 设置index页面的旋转中心轴为左侧边缘
                        this.centerXList[proxy.index] = '0%';
                    } else {
                        // position小于-1时表示向左完全滑出区域,大于1时表示向右完全滑出区域,重置角度
                        angle = 0;
                    }
                    // 修改index页的旋转角
                    this.angleList[proxy.index] = angle;
                }
            })

        }
        .height('100%')
        .width('100%')
    }
}

更多关于HarmonyOS鸿蒙Next中router跳转如何添加翻转的3D动画?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用router跳转添加翻转3D动画需通过pageTransition接口实现。在目标页面的aboutToAppear方法中调用PageTransitiononEnteronPopEnter方法,配置旋转动画参数。例如,设置rotate属性定义翻转轴和角度,结合transform控制3D效果。动画类型需指定为PageTransitionEnterPageTransitionExit,并配置插值曲线与时长。最终通过router.pushUrl触发跳转即可呈现3D翻转效果。

在HarmonyOS Next中,可以通过windowClasswindowTransition为router跳转添加3D翻转动画。具体实现如下:

  1. 在目标页面的aboutToAppear方法中设置窗口转场动画:
import window from '@ohos.window';

aboutToAppear() {
  let windowClass = window.getLastWindow(this.context);
  windowClass.setWindowTransition('RotateAnimation', {
    // 设置Y轴旋转180度
    rotate: { y: 1, angle: 180 },
    // 设置动画参数
    duration: 500,
    curve: curves.cubicBezier(0.5, 0.1, 0.1, 1.0)
  });
}
  1. 在router.pushUrl跳转时指定动画参数:
router.pushUrl({
  url: 'pages/TargetPage',
  windowTransition: {
    type: 'RotateAnimation',
    duration: 500,
    curve: curves.cubicBezier(0.5, 0.1, 0.1, 1.0)
  }
});
  1. 如需自右向左效果,可配合translate动画:
windowClass.setWindowTransition('RotateAnimation', {
  rotate: { y: 1, angle: 180 },
  translate: { x: -100 }, // 向左平移
  duration: 500,
  curve: curves.cubicBezier(0.25, 0.46, 0.45, 0.94)
});

注意:需要导入@ohos.window@ohos.router模块,动画参数可根据实际效果调整。

回到顶部