首页 > 其他分享 >鸿蒙NEXT应用示例:切换图片动画

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

时间:2024-11-14 21:43:27浏览次数:1  
标签:动画 鸿蒙 示例 cellWidth NEXT State 设置 imageUrls 图片

 

【引言】

在鸿蒙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
        })
      })
    }
  }
}

@Component
struct 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
        })
      })
    }
  }
}

@Component
struct 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度
        })
      })
    }
  }
}

@Component
struct 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
@Component
struct Test {
  build() {
    Column({ space: 30 }) {
      // 无限循环切换到下一张图片(平移)
      SlideTransition()
      // 无限循环切换到下一张图片(翻转)
      FlipTransition()
      // 无限循环切换到下一张图片(缩放)
      ScaleTransition()
      // 无限循环切换到下一张图片(淡入淡出)
      FadeTransition()
    }.height('100%').width('100%')
  }
}

  

标签:动画,鸿蒙,示例,cellWidth,NEXT,State,设置,imageUrls,图片
From: https://www.cnblogs.com/zhongcx/p/18546878

相关文章

  • 鸿蒙NEXT开发案例:年龄计算
     ​【引言】本案例的目标是开发一款年龄计算器应用,该应用能够根据用户输入的出生日期,计算出用户的实际年龄、虚岁、星座、生肖等信息。同时,应用还将提供距离下次公历和农历生日的天数及星期等信息。为了实现这些功能,我们将使用ArkTS和ArkUI作为开发语言,并借助@nutpi/calendar......
  • python调用扣子coze智能体示例
    """版本号:1.0日期:2024/11/14描述:"""importuuidimportjwtimporttimeimportrequests#OAuth应用的相关信息,需从扣子平台获取并替换APP_ID=""#auth应用idPUBLIC_KEY_FINGERPRINT=""#公钥PRIVATE_KEY_PATH="private_......
  • layui-laydate时间日历控件详细示例
     layui下载地址:http://www.layui.com/此控件可使用layui或者独立版的layDate,两者初始化有些不同1.在layui模块中使用layui.code<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>layDate快速使用</title><linkrel="stylesheet"......
  • 原子类保证多线程环境下的数据安全的示例
    原子类保证多线程环境下的数据安全的示例 1、原子整型类保证多线程环境下的数据安全示例:packagecom.joyupx.cms.example.thread.concurrent.atomic;importlombok.extern.slf4j.Slf4j;importjava.util.concurrent.atomic.AtomicInteger;/***原子性操作*多线程......
  • Arduino语法详解_含示例详解
    Arduino的程序可以划分为三个主要部分:结构、变量(变量与常量)、函数。  结构部分 一、结构1.1setup()1.2loop()二、结构控制2.1if2.2if...else2.3for2.4switchcase2.5while2.6do...while2.7break2.8continue2.9return2.10goto三、扩展语法......
  • Jmeter (5.6.3) Windows 使用示例
    步骤:1.下载apache-jmeter-5.6.3.zip2.解压,在环境变量Path中,新增jMeter的bin文件夹的路径3.在bin文件夹中,双击jmeter.bat->打开JMeter4.在JMeter的窗口中:文件->新建(创建测试计划)5.测试计划右键:添加->线程(用户)->线程组6.线程组右键:添加->取样器->HTTP请求7.HTTP请......
  • 鸿蒙Navigation知识点详解
    Navigation是路由导航的根视图容器,一般作为页面(@Entry)的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。一次开发,多......
  • 鸿蒙学习生态应用开发能力全景图-鸿蒙生态伙伴 SDK 市场(4)
    鸿蒙生态伙伴SDK市场帮助开发者获得更优质安全的闭源SDK,与SDK伙伴、开发者共建一站式的SDK选用平台,实现开发者、SDK伙伴和华为共赢。鸿蒙生态伙伴SDK市场汇聚热门SDK助力开发者构建高品质鸿蒙原生应用。同时伙伴SDK市场通过SDK签名认证、安全检测/审核、SDK......
  • 原生鸿蒙政务行业应用开发模板上线,近200个政务服务应用已上架
    一直以来,发展新质生产力对数字政府建设意义重大。华为原生鸿蒙之夜暨华为全场景新品发布会上,华为宣布从底座上全面突破操作系统的核心技术,实现了操作系统的自主可控。截至发布会,鸿蒙原生应用和元服务上架数已突破1.5万个,已有180余个政务服务一网通办平台、公积金类、医保服务类和......
  • HarmonyOS NEXT开发实战教程-记账app
    今天分享的实战教程是一款记账app,最近分享的项目都是纯页面,没有服务端,没有数据接口,因为鸿蒙开发主要就是写页面,都是前端嘛。如果有友友想要完整的项目可以找幽蓝君定制,想学服务端开发的话幽蓝君也可以写。话不多说,看一下记账app的效果图: 下面为大家分享本项目的开发教程,其实......