写点什么

鸿蒙 NEXT 应用示例:切换图片动画

作者:zhongcx
  • 2024-11-14
    广东
  • 本文字数:8021 字

    阅读完需:约 26 分钟

【引言】

在鸿蒙 NEXT 应用开发中,实现图片切换动画是一项常见的需求。本文将介绍如何使用鸿蒙应用框架中的组件和动画功能,实现不同类型的图片切换动画效果。

【环境准备】

电脑系统:windows 10

开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

工程版本:API 12

真机:mate60 pro

语言:ArkTS、ArkUI

权限:ohos.permission.INTERNET(示例图片是 url 所以需要网络权限)

【动画说明】

1. 淡入淡出动画(FadeTransition)

FadeTransition 组件定义了一个淡入淡出的图片切换效果。通过设置图片的透明度实现渐变效果,让当前显示的图片逐渐消失,同时下一张图片逐渐显示出来。点击按钮时触发淡入淡出动画,实现图片的无限循环切换。

2. 缩放动画(ScaleTransition)

ScaleTransition 组件实现了图片的缩放切换效果。通过控制图片的缩放比例,让当前显示的图片缩小消失,同时下一张图片放大显示出来。点击按钮时触发缩放动画,实现图片的无限循环切换。

3. 翻转动画(FlipTransition)

FlipTransition 组件展示了图片的翻转切换效果。通过设置图片的旋转角度,让当前显示的图片沿 Y 轴翻转消失,同时下一张图片沿 Y 轴翻转显示出来。点击按钮时触发翻转动画,实现图片的无限循环切换。

4. 平移动画(SlideTransition)

SlideTransition 组件实现了图片的平移切换效果。通过控制图片在 X 轴方向的平移距离,让当前显示的图片向左移出屏幕,同时下一张图片从右侧移入屏幕。点击按钮时触发平移动画,实现图片的无限循环切换。

通过以上四种不同的图片切换动画效果,可以为鸿蒙 NEXT 应用增添更加生动和吸引人的用户体验。开发者可以根据实际需求选择合适的动画效果,为应用界面注入更多活力和创意。

【完整代码】

@Component  // 定义一个组件struct FadeTransition { // 定义一个名为FadeTransition的结构体  @State cellWidth: number = 200 // 定义并初始化一个名为cellWidth的状态变量,初始值为200,表示单元格宽度  @State imageUrls: string[] = [// 定义并初始化一个名为imageUrls的状态变量,存储图片的URL数组    'https://img2.baidu.com/it/u=3029837478,1144772205&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',    'https://img2.baidu.com/it/u=186808850,2178610585&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',    'https://img2.baidu.com/it/u=246493236,1763577649&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',    'https://img0.baidu.com/it/u=3081415685,2219539125&fm=253&fmt=auto&app=138&f=JPEG?w=809&h=800'  ]  @State selectedIndex: number = 0 // 定义并初始化一个名为selectedIndex的状态变量,表示当前选中的图片索引  @State currentImage: string = "" // 定义并初始化一个名为currentImage的状态变量,表示当前显示的图片  @State nextImage: string = "" // 定义并初始化一个名为nextImage的状态变量,表示下一张要显示的图片  @State isRunningAnimation: boolean = false // 定义并初始化一个名为isRunningAnimation的状态变量,表示动画是否正在运行  @State opacity1: number = 1.0 // 定义并初始化一个名为opacity1的状态变量,表示当前图片的透明度  @State opacity2: number = 0.0 // 定义并初始化一个名为opacity2的状态变量,表示下一张图片的透明度
aboutToAppear(): void { // 定义一个方法,用于设置当前显示的图片和下一张要显示的图片 this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] }
build() { // 定义一个方法,用于构建组件 Column({ space: 30 }) { // 创建一个垂直布局的Column组件,设置间距为30 Stack() { // 创建一个Stack组件 Image(this.nextImage)// 显示下一张图片 .width(`${this.cellWidth}px`)// 设置图片宽度 .height(`${this.cellWidth}px`)// 设置图片高度 .opacity(this.opacity2) // 设置图片透明度 Image(this.currentImage)// 显示当前图片 .width(`${this.cellWidth}px`)// 设置图片宽度 .height(`${this.cellWidth}px`)// 设置图片高度 .opacity(this.opacity1) // 设置图片透明度 }.height(`${this.cellWidth}px`).width('100%') // 设置Stack组件的高度和宽度
Button('下一张 (淡入淡出)').onClick(() => { // 创建一个按钮,点击按钮执行淡入淡出动画 if (this.isRunningAnimation) { // 如果动画正在运行,则返回 return } this.isRunningAnimation = true // 设置动画正在运行 // 淡入淡出动画示例 animateTo({ // 执行动画 duration: 400, // 设置动画持续时间 onFinish: () => { // 动画结束时执行的操作 this.currentImage = this.nextImage // 设置当前图片为下一张图片 this.selectedIndex++ // 选中图片索引加一 animateTo({ // 执行动画 duration: 100, // 设置动画持续时间 onFinish: () => { // 动画结束时执行的操作 this.opacity1 = 1 // 设置当前图片透明度为1 this.opacity2 = 0 // 设置下一张图片透明度为0 this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 this.isRunningAnimation = false // 设置动画结束 } }, () => { }) } }, () => { this.opacity1 = 0 // 设置当前图片透明度为0 this.opacity2 = 1 // 设置下一张图片透明度为1 }) }) } }}
@Componentstruct ScaleTransition { @State cellWidth: number = 200 // 单元格宽度 @State imageUrls: string[] = [// 图片URL数组 'https://img2.baidu.com/it/u=3029837478,1144772205&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img2.baidu.com/it/u=186808850,2178610585&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img2.baidu.com/it/u=246493236,1763577649&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img0.baidu.com/it/u=3081415685,2219539125&fm=253&fmt=auto&app=138&f=JPEG?w=809&h=800' ] @State selectedIndex: number = 0 // 当前选中的图片索引 @State currentImage: string = "" // 当前显示的图片 @State nextImage: string = "" // 下一张要显示的图片 @State isRunningAnimation: boolean = false // 动画是否正在运行 @State scale1: number = 1.0 // 当前图片的缩放比例 @State scale2: number = 0.0 // 下一张图片的缩放比例
aboutToAppear(): void { this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 }
build() { Column({ space: 30 }) { // 构建垂直布局 Stack() { // 堆叠布局 Image(this.nextImage)// 显示下一张图片 .width(`${this.cellWidth}px`)// 设置宽度 .height(`${this.cellWidth}px`)// 设置高度 .scale({ x: this.scale2, y: this.scale2 }) // 设置缩放比例 Image(this.currentImage)// 显示当前图片 .width(`${this.cellWidth}px`)// 设置宽度 .height(`${this.cellWidth}px`)// 设置高度 .scale({ x: this.scale1, y: this.scale1 }) // 设置缩放比例 }.height(`${this.cellWidth}px`).width('100%') // 设置堆叠布局的高度和宽度
Button('下一张 (缩放)').onClick(() => { // 创建按钮并设置点击事件 if (this.isRunningAnimation) { // 如果动画正在运行,直接返回 return } this.isRunningAnimation = true // 标记动画正在运行 // 缩放动画示例 animateTo({ // 执行动画 duration: 200, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.scale1 = 0 // 设置当前图片缩放比例为0 animateTo({ // 执行第二段动画 duration: 200, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.currentImage = this.nextImage // 切换到下一张图片 this.selectedIndex++ // 更新选中的图片索引 animateTo({ // 执行第三段动画 duration: 100, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.scale1 = 1 // 设置当前图片缩放比例为1 this.scale2 = 0 // 设置下一张图片缩放比例为0 this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 this.isRunningAnimation = false // 标记动画结束 } }, () => { }) } }, () => { this.scale2 = 1 // 设置下一张图片缩放比例为1 }) } }, () => { this.scale1 = 0 // 设置当前图片缩放比例为0 }) }) } }}
@Componentstruct FlipTransition { @State cellWidth: number = 200 // 单元格宽度 @State imageUrls: string[] = [// 图片URL数组 'https://img2.baidu.com/it/u=3029837478,1144772205&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img2.baidu.com/it/u=186808850,2178610585&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img2.baidu.com/it/u=246493236,1763577649&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img0.baidu.com/it/u=3081415685,2219539125&fm=253&fmt=auto&app=138&f=JPEG?w=809&h=800' ] @State selectedIndex: number = 0 // 当前选中的图片索引 @State currentImage: string = "" // 当前显示的图片 @State nextImage: string = "" // 下一张要显示的图片 @State isRunningAnimation: boolean = false // 动画是否正在运行 @State angle1: number = 0 // 当前图片的旋转角度 @State angle2: number = 90 // 下一张图片的旋转角度
aboutToAppear(): void { this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 }
build() { Column({ space: 30 }) { // 构建垂直布局 Stack() { // 堆叠布局 Image(this.nextImage)// 显示下一张图片 .width(`${this.cellWidth}px`)// 设置宽度 .height(`${this.cellWidth}px`)// 设置高度 .rotate({ x: 0, y: 1, z: 0, angle: this.angle2 // 设置旋转角度 }) Image(this.currentImage)// 显示当前图片 .width(`${this.cellWidth}px`)// 设置宽度 .height(`${this.cellWidth}px`)// 设置高度 .rotate({ x: 0, y: 1, z: 0, angle: this.angle1 // 设置旋转角度 }) }.height(`${this.cellWidth}px`).width('100%') // 设置堆叠布局的高度和宽度
Button('下一张 (翻转)').onClick(() => { // 创建按钮并设置点击事件 if (this.isRunningAnimation) { // 如果动画正在运行,直接返回 return } this.isRunningAnimation = true // 标记动画正在运行 // 翻转动画示例 animateTo({ // 执行动画 duration: 200, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.angle1 = -90 // 设置当前图片旋转角度为-90度 animateTo({ // 执行第二段动画 duration: 200, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.currentImage = this.nextImage // 切换到下一张图片 this.selectedIndex++ // 更新选中的图片索引 animateTo({ // 执行第三段动画 duration: 100, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.angle1 = 0 // 设置当前图片旋转角度为0度 this.angle2 = 90 // 设置下一张图片旋转角度为90度 this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 this.isRunningAnimation = false // 标记动画结束 } }, () => { }) } }, () => { this.angle2 = 0 // 设置下一张图片旋转角度为0度 }) } }, () => { this.angle1 = -90 // 设置当前图片旋转角度为-90度 }) }) } }}
@Componentstruct SlideTransition { @State cellWidth: number = 200 // 单元格宽度 @State imageUrls: string[] = [// 图片URL数组 'https://img2.baidu.com/it/u=3029837478,1144772205&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img2.baidu.com/it/u=186808850,2178610585&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img2.baidu.com/it/u=246493236,1763577649&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img0.baidu.com/it/u=3081415685,2219539125&fm=253&fmt=auto&app=138&f=JPEG?w=809&h=800' ] @State selectedIndex: number = 0 // 当前选中的图片索引 @State translateX1: number = 0 // 当前图片的X轴平移距离 @State translateX2: number = 0 // 下一张图片的X轴平移距离 @State zIndex2: number = 0 // 下一张图片的层级 @State zIndex1: number = 1 // 当前图片的层级 @State currentImage: string = "" // 当前显示的图片 @State nextImage: string = "" // 下一张要显示的图片 @State isRunningAnimation: boolean = false // 动画是否正在运行
aboutToAppear(): void { this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 }
build() { Column({ space: 30 }) { // 构建垂直布局 Stack() { // 堆叠布局 Image(this.nextImage)// 显示下一张图片 .width(`${this.cellWidth}px`)// 设置宽度 .height(`${this.cellWidth}px`)// 设置高度 .translate({ x: `${this.translateX2}px`, y: 0 })// 设置X轴平移距离 .zIndex(this.zIndex2) // 设置层级 Image(this.currentImage)// 显示当前图片 .width(`${this.cellWidth}px`)// 设置宽度 .height(`${this.cellWidth}px`)// 设置高度 .translate({ x: `${this.translateX1}px`, y: 0 })// 设置X轴平移距离 .zIndex(this.zIndex1) // 设置层级 }.height(`${this.cellWidth}px`).width('100%') // 设置堆叠布局的高度和宽度
Button('下一张 (平移)').onClick(() => { // 创建按钮并设置点击事件 if (this.isRunningAnimation) { // 如果动画正在运行,直接返回 return } this.isRunningAnimation = true // 标记动画正在运行 // 平移动画示例 animateTo({ // 执行动画 duration: 200, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.zIndex1 = 0 // 设置当前图片层级为0 this.zIndex2 = 1 // 设置下一张图片层级为1 animateTo({ // 执行第二段动画 duration: 200, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.currentImage = this.nextImage // 切换到下一张图片 this.selectedIndex++ // 更新选中的图片索引 animateTo({ // 执行第三段动画 duration: 100, // 动画持续时间 onFinish: () => { // 动画结束时的回调 this.zIndex1 = 1 // 设置当前图片层级为1 this.zIndex2 = 0 // 设置下一张图片层级为0 this.currentImage = this.imageUrls[(this.selectedIndex + 0) % this.imageUrls.length] // 设置当前显示的图片 this.nextImage = this.imageUrls[(this.selectedIndex + 1) % this.imageUrls.length] // 设置下一张要显示的图片 this.isRunningAnimation = false // 标记动画结束 } }, () => { }) } }, () => { this.translateX1 = 0 // 设置当前图片X轴平移距离为0 this.translateX2 = 0 // 设置下一张图片X轴平移距离为0 }) } }, () => { this.translateX1 = -this.cellWidth / 2 // 设置当前图片X轴平移距离为单元格宽度的一半 this.translateX2 = +this.cellWidth / 2 // 设置下一张图片X轴平移距离为单元格宽度的一半 }) }) } }}
@Entry@Componentstruct Test { build() { Column({ space: 30 }) { // 无限循环切换到下一张图片(平移) SlideTransition() // 无限循环切换到下一张图片(翻转) FlipTransition() // 无限循环切换到下一张图片(缩放) ScaleTransition() // 无限循环切换到下一张图片(淡入淡出) FadeTransition() }.height('100%').width('100%') }}
复制代码


用户头像

zhongcx

关注

还未添加个人签名 2024-09-27 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙NEXT应用示例:切换图片动画_鸿蒙_zhongcx_InfoQ写作社区