本文会学习如何设置OpenHarmony的转场动画,主要包括页面的转场动画和组件的转场动画。所谓转场动画,是指在两个页面之间切换或组件显示/隐藏等操作时以动画效果展现。下图是本文案例的主界面。点击每一个按钮,会展示特定的转场动画。

#DAYU200体验官# OpenHarmony3.1中的转场动画_鸿蒙

1. 底部滑入动画
这种动画效果可以让A页面切换到B页面时,B页面从底端往上展现。这是通过slide方法设置的动画效果,代码如下:

  pageTransition() {

// 页面入场组件:SlideEffect.Bottom 设置到入场时表示从下边滑入,出场时表示滑出到下边。
PageTransitionEnter({ duration: 600, curve: Curve.Smooth })
.slide(SlideEffect.Bottom)

// 页面退场组件:SlideEffect.Bottom 设置到入场时表示从下边滑入,出场时表示滑出到下边。
PageTransitionExit({ duration: 600, curve: Curve.Smooth })
.slide(SlideEffect.Bottom)
}

动画完成,会显示下图的页面:

#DAYU200体验官# OpenHarmony3.1中的转场动画_OpenHarmony3.1_02

2. 页面自定义转场1
下面的代码可以通过不同的特效方法自定义转场动画,例如,通过opacity方法设置透明度动画,通过scale方法设置缩放动画。这段代码让页面进场时透明度从0.2变到1,尺寸比例从0(未显示)变到原始大小(1)。

pageTransition() {

// 页面入场组件
PageTransitionEnter({ duration: 600, curve: Curve.Smooth })
.opacity(0.2) //入场时候透明度从0.2到1
.scale({ x: 0, y: 0 }) //入场时x、y轴缩放从0变化到1

// 页面退场组件
PageTransitionExit({ duration: 600, curve: Curve.Smooth })
.translate({ x: 500, y: 500 }) //退场时x、y轴的偏移量为500
}

动画完成,会显示下图的页面:

#DAYU200体验官# OpenHarmony3.1中的转场动画_鸿蒙_03

3. 页面自定义转场2
这也是一种自定义转场动画,用来控制Image组件的透明度。当入场时,Image的透明度会从0变到1(逐渐显示),退场时Image的透明度会从1变到0(逐渐消失)。

@Entry
@Component
struct FullCustomTransition {
@State myProgress: number = 1

build() {
Stack() {
Image($rawfile('image1.jpg'))
.objectFit(ImageFit.Cover)
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
.opacity(this.myProgress)
.scale({ x: this.myProgress, y: this.myProgress })
.rotate({ x: 0, y: 0, z: 1, angle: 360 * this.myProgress })
}

pageTransition() {

// 页面入场组件: 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0% -- 100%)
PageTransitionEnter({ duration: 800, curve: Curve.Smooth })
.onEnter((type: RouteType, progress: number) => {
this.myProgress = progress // 页面入场式myProgress从0变化到1
})

// 页面退场组件: 进场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0% -- 100%)
PageTransitionExit({ duration: 800, curve: Curve.Smooth })
.onExit((type: RouteType, progress: number) => {
this.myProgress = 1 - progress //页面退场式myProgress从1变化到0
})
}
}

动画完成,会显示下图的页面:

#DAYU200体验官# OpenHarmony3.1中的转场动画_OpenHarmony_04

4. 组件内转场
这种动画是针对组件的,而不是针对页面的。既然是针对组件的,就需要对组件调用transition方法。下面的代码对组件完成了插入和删除动画,也就是组件添加时x、y轴缩放从0.5变化到1,透明度从0到1。 组件移除时沿y轴旋转360度,x、y轴缩放从1变化到0。完整的实现代码如下:

@Component
struct ComponentItem {
build() {
Stack({ alignContent: Alignment.Center }) {
Image($rawfile('image3.png'))
.objectFit(ImageFit.Cover)
.width('100%')
.height(120)
.borderRadius(15)
}
.height(120)
.borderRadius(15)
.width('80%')
.padding({ top: 20 })
// 组件添加时x、y轴缩放从0.5变化到1,透明度从0到1
.transition({ type: TransitionType.Insert, scale: { x: 0.5, y: 0.5 }, opacity: 0 })
// 组件移除时沿y轴旋转360度,x、y轴缩放从1变化到0,
.transition({ type: TransitionType.Delete, rotate: { x: 0, y: 1, z: 0, angle: 360 }, scale: { x: 0, y: 0 } })
}
}

@Entry
@Component
struct ComponentTransition {
@State private isShow: boolean= false

build() {
Column() {
if (this.isShow) {
ComponentItem()
}

ComponentItem()

Button("Toggle")
.onClick(() => {
//执行动效,动效时长600ms
animateTo({ duration: 600 }, () => {
this.isShow = !this.isShow;
})
})
.height(45)
.width(200)
.fontColor(Color.Black)
.backgroundColor('rgb(181,222,224)')
.margin({ top: 20 })
}
.padding({ left: 20, right: 20 })
.backgroundColor('#FFECECEC')
.height('100%')
.width('100%')
}
}

当点击按钮时,显示按钮的效果如下图所示。

#DAYU200体验官# OpenHarmony3.1中的转场动画_OpenHarmony_05

5. 共享元素转场
所有共享元素,就是指一个元素(组件)看起来属于页面A,又属于页面B,这个元素就成为共享元素。典型的应用按钮是共享元素一开始以小图显示,然后点击,会在整个页面显示。下图是小图的效果。

#DAYU200体验官# OpenHarmony3.1中的转场动画_OpenHarmony_06


点击后,会整屏显示,效果如下图所示:

#DAYU200体验官# OpenHarmony3.1中的转场动画_鸿蒙_07

这个功能由两个ets文件完成,其中ShareItem.ets是小图的,代码如下,其中共享元素转场属性通过sharedTransition方法设置

mport router from '@system.router'

@Entry
@Component
struct ShareItem {
build() {
Flex() {
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Stack() {
Image($rawfile('image2.jpg'))
// 设置共享元素转场属性
.sharedTransition('imageId', { duration: 600, curve: Curve.Smooth, delay: 100 })
.onClick(() => {
router.push({ uri: 'pages/SharePage' })
})
.objectFit(ImageFit.Cover)
.height('100%')
.width('100%')
.borderRadius(15)
}
.height('100%')
.width('100%')

Text('点击查看共享元素转场动效')
.fontSize(20)
.fontColor(Color.Black)
.fontWeight(FontWeight.Regular)
.margin({ left: 10, right: 10 })

}
.height(120)
.backgroundColor('rgb(181,222,224)')
.borderRadius(15)
.margin({ top: 20 })
}
.width('100%')
.padding({ left: 16, right: 16 })
.backgroundColor('#FFECECEC')
}
}

另外一个页面是SharePage,用于显示大图,代码如下,点击图像,同样可以切换回小图(ShareItem)。

@Entry
@Component
struct SharePage {
build() {
Stack() {
Image($rawfile('image2.jpg'))
// 设置共享元素转场属性
.sharedTransition('imageId', { duration: 1000, curve: Curve.Smooth, delay: 100 })
.objectFit(ImageFit.Cover)
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
}


​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​