当前位置: 首页 > news >正文

鸿蒙案例---生肖抽卡

案例源码:

Zodiac_cards: 鸿蒙生肖抽奖卡片

效果演示

初始布局

1. Badge 角标组件

此处为语雀内容卡片,点击链接查看:https://www.yuque.com/kevin-nzthp/lvl039/rccg0o4pkp3v6nua

2. Grid 布局

// 定义接口
interface ImageCount {
  url: ResourceStr,
  count: number
}

@Entry
  @Component
  struct Index {
    @State images: ImageCount[] = [
      { url: '/images/bg_00.png', count: 0 },
      { url: '/images/bg_01.png', count: 1 },
      { url: '/images/bg_02.png', count: 2 },
      { url: '/images/bg_03.png', count: 3 },
      { url: '/images/bg_04.png', count: 4 },
      { url: '/images/bg_05.png', count: 5 },
    ]

    // 控制遮罩的显隐
    @State maskOpacity: number = 0 // 透明度
    @State maskIndex: number = -1; // 显示层级

    // 控制图片的缩放
    @State maskImgX: number = 0 // 水平缩放比
    @State maskImgY: number = 0 // 垂直缩放比

    build() {
      Stack() {
        Column() {
          Grid() {
            ForEach(this.images, (item: ImageCount) => {
              GridItem() {
                Badge({
                  count: item.count,
                  position: BadgePosition.RightTop,
                  style: {
                    badgeSize: this.maskImgX,
                    fontSize: this.maskImgY
                  }
                }) {
                  Image(item.url)
                    .width(80)
                }
              }
            })
          }
          .rowsTemplate('1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr')
            .width('100%')
            .height(300)
            .margin({ top: 100 })


          Button('立即抽卡')
            .width(200)
            .backgroundColor('#ed5b8c')
            .margin({ top: 50 })
            .onClick(()=>{
              // 点击时,修改遮罩参数,让遮罩显示
              this.maskOpacity = 1
              this.maskIndex = 99
              // 图片需要缩放
              this.maskImgX = 1
              this.maskImgY = 1
            })

        }
        .width('100%')
          .height('100%')
          .backgroundColor(Color.Pink)

        // 抽卡遮盖层
        Column({space: 30}) {
          Text('获得生肖卡')
            .fontColor('#f5ebcf')
            .fontSize(25)
            .fontWeight(FontWeight.Bold)
          Image('/images/img_00.png')
            .width(200)
            //控制元素的缩放
            .scale({
              x: this.maskImgX,
              y: this.maskImgY
            })

          Button('开心收下')
            .width(200)
            .height(50)
            .backgroundColor(Color.Transparent)
            .border({ width: 2 ,color:'#fff9e0'})
            .onClick(()=>{
              // 控制弹层显隐
              this.maskOpacity = 0
              this.maskIndex = -1
              // 重置缩放比为0,便于下一次进行缩放
              this.maskImgX = 0
              this.maskImgY = 0
            })
        }
        .justifyContent(FlexAlign.Center)
          .width('100%')
          .height('100%')
          .backgroundColor('#cc000000')
          // 设置透明度
          .opacity(this.maskOpacity)
          .zIndex(this.maskIndex)
          // 动画 animation 当我们元素有状态的改变,可以添加animation做动画
          .animation({
            duration: 500
          })
      }
    }
  }

抽卡遮罩层

静态页面

点击立即抽卡按钮后,会进入遮罩层,显示抽取的卡片,此时抽卡的页面转换为背景图,使用层叠布局

// 定义图片接口
interface ImageCount {
  url: ResourceStr,
  count: number
}

@Entry
  @Component
  struct Index {
    // 定义图片渲染数组
    @State images: ImageCount[] = [
      { url: '/images/bg_00.png', count: 0 },
      { url: '/images/bg_01.png', count: 1 },
      { url: '/images/bg_02.png', count: 2 },
      { url: '/images/bg_03.png', count: 3 },
      { url: '/images/bg_04.png', count: 4 },
      { url: '/images/bg_05.png', count: 5 },
    ]

    build() {
      Stack(){
        Column() {
          Grid() {
            ForEach(this.images, (item: ImageCount) => {
              GridItem() {
                Badge({
                  count: item.count,
                  position: BadgePosition.RightTop,
                  style: {
                    fontSize: 12,
                    badgeSize: 16
                  }
                }) {
                  Image(item.url)
                    .width(80)
                }
              }
            })
          }
          .rowsTemplate('1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr')
            .height(300)
            .margin({top: 50, bottom: 50})
          // .backgroundColor(Color.Pink)

          Button('立即抽卡')
            .width(200)
            .backgroundColor('#ED5B8C')
        }

        Column({space: 30}){
          Text('获得生肖卡')
            .fontColor('#F3EAD3')
            .fontWeight(700)
            .fontSize(24)

          Image('/images/img_00.png')
            .width(200)

          Button('开心收下')
            .width(200)
            .border({
              width: 2,
              color:'#9F9C90',
            })
            .backgroundColor(Color.Transparent)
        }
        .backgroundColor('#cc000000')
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)

      }
    }
  }

抽卡遮罩层- 显隐效果控制

添加状态变量控制遮罩层 Z 轴 和 不透明度的数值.

当点击 “立即抽卡”按钮时,显示遮罩层。(此时不能隐藏)

当点击 遮罩层“开心收下”按钮时,隐藏遮罩层。

添加动画

添加遮罩层图片的缩放

效果

// 定义图片接口
interface ImageCount {
  url: ResourceStr,
  count: number
}

@Entry
  @Component
  struct Index {
    // 定义图片渲染数组
    @State images: ImageCount[] = [
      { url: '/images/bg_00.png', count: 0 },
      { url: '/images/bg_01.png', count: 1 },
      { url: '/images/bg_02.png', count: 2 },
      { url: '/images/bg_03.png', count: 3 },
      { url: '/images/bg_04.png', count: 4 },
      { url: '/images/bg_05.png', count: 5 },
    ]
    // 控制遮罩的显隐
    @State maskOpacity: number = 0 // 透明度
    @State maskIndex: number = -1; // 显示层级
    // 控制遮罩层图片的缩放
    @State maskImgScaleX: number = 0 // 水平缩放比
    @State maskImgScaleY: number = 0 // 垂直缩放比

    // 获取图片

    build() {
      Stack() {
        // 抽卡层
        Column() {
          Grid() {
            ForEach(this.images, (item: ImageCount) => {
              GridItem() {
                Badge({
                  count: item.count,
                  position: BadgePosition.RightTop,
                  style: {
                    fontSize: 12,
                    badgeSize: 16
                  }
                }) {
                  Image(item.url)
                    .width(80)
                }
              }
            })
          }
          .rowsTemplate('1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr')
            .height(300)
            .margin({ top: 50, bottom: 50 })

          // .backgroundColor(Color.Pink)

          Button('立即抽卡')
            .width(200)
            .backgroundColor('#ED5B8C')
            .onClick(() => {
              // 点击时,修改遮罩参数,让遮罩显示
              this.maskOpacity = 1
              this.maskIndex = 99
              // 点击时修改遮罩层图片的缩放比
              this.maskImgScaleX = 1
              this.maskImgScaleY = 1
            })
        }

        // 遮罩层
        Column({ space: 30 }) {
          Text('获得生肖卡')
            .fontColor('#F3EAD3')
            .fontWeight(700)
            .fontSize(24)

          Image('/images/img_00.png')
            .width(200)
            .scale({
              //控制图片的缩放
              x: this.maskImgScaleX,
              y: this.maskImgScaleY
            })
            .animation({
              // 动画
              duration: 500
            })

          Button('开心收下')
            .width(200)
            .border({
              width: 2,
              color: '#9F9C90',
            })
            .backgroundColor(Color.Transparent)
            .onClick(() => {
              // 点击时,修改遮罩参数,让遮罩隐藏
              this.maskOpacity = 0
              this.maskIndex = -1
              //   // 点击时修改遮罩层图片的缩放比为1:1
              this.maskImgScaleX = 0
              this.maskImgScaleY = 0
            })
        }
        .zIndex(this.maskIndex)
          .opacity(this.maskOpacity)
          .backgroundColor('#cc000000')
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)

      }
    }
  }

随机卡片

效果演示:

要获得 0-5 的整数索引,随机抽取卡片

此时可以获取随机卡片,接下来要将抽到的随机卡片显示在主页面并右上角角标显示。

// 定义图片接口
interface ImageCount {
  url: ResourceStr,
  count: number
}

@Entry
  @Component
  struct Index {
    // 定义图片渲染数组
    @State images: ImageCount[] = [
      { url: '/images/bg_00.png', count: 0 },
      { url: '/images/bg_01.png', count: 0 },
      { url: '/images/bg_02.png', count: 0 },
      { url: '/images/bg_03.png', count: 0 },
      { url: '/images/bg_04.png', count: 0 },
      { url: '/images/bg_05.png', count: 0 },
    ]
    // 控制遮罩的显隐
    @State maskOpacity: number = 0 // 透明度
    @State maskIndex: number = -1; // 显示层级
    // 控制遮罩层图片的缩放
    @State maskImgScaleX: number = 0 // 水平缩放比
    @State maskImgScaleY: number = 0 // 垂直缩放比
    // 获取遮罩层选择的图片Index
    @State maskImgIndex: number = 0

    build() {
      Stack() {
        // 抽卡层
        Column() {
          Grid() {
            ForEach(this.images, (item: ImageCount) => {
              GridItem() {
                Badge({
                  count: item.count,
                  position: BadgePosition.RightTop,
                  style: {
                    fontSize: 12,
                    badgeSize: 16
                  }
                }) {
                  Image(item.url)
                    .width(80)
                }
              }
            })
          }
          .rowsTemplate('1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr')
            .height(300)
            .margin({ top: 50, bottom: 50 })

          // .backgroundColor(Color.Pink)

          Button('立即抽卡')
            .width(200)
            .backgroundColor('#ED5B8C')
            .onClick(() => {
              // 点击时,修改遮罩参数,让遮罩显示
              this.maskOpacity = 1
              this.maskIndex = 99
              // 点击时修改遮罩层图片的缩放比
              this.maskImgScaleX = 1
              this.maskImgScaleY = 1
              //   // 随机获取图片的Index
              this.maskImgIndex = Math.floor(Math.random() * 6)
            })
        }

        // 遮罩层
        Column({ space: 30 }) {
          Text('获得生肖卡')
            .fontColor('#F3EAD3')
            .fontWeight(700)
            .fontSize(24)

          Image(`/images/img_0${this.maskImgIndex}.png`)
            .width(200)
            .scale({
              //控制图片的缩放
              x: this.maskImgScaleX,
              y: this.maskImgScaleY
            })
            .animation({
              // 动画
              duration: 500
            })

          Button('开心收下')
            .width(200)
            .border({
              width: 2,
              color: '#9F9C90',
            })
            .backgroundColor(Color.Transparent)
            .onClick(() => {
              // 点击时,修改遮罩参数,让遮罩隐藏
              this.maskOpacity = 0
              this.maskIndex = -1
              //   // 点击时修改遮罩层图片的缩放比为1:1
              this.maskImgScaleX = 0
              this.maskImgScaleY = 0
              //   开心收下
              this.images[this.maskImgIndex] = {
                url: `/images/img_0${this.maskImgIndex}.png`,
                count: this.images[this.maskImgIndex].count + 1
              }
            })
        }
        .zIndex(this.maskIndex)
          .opacity(this.maskOpacity)
          .backgroundColor('#cc000000')
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)

    }
  }
}

抽大奖遮罩层

静态页面

// 定义图片接口
interface ImageCount {
  url: ResourceStr,
  count: number
}

@Entry
@Component
struct Index {
  // 定义图片渲染数组
  @State images: ImageCount[] = [
    { url: '/images/bg_00.png', count: 0 },
    { url: '/images/bg_01.png', count: 0 },
    { url: '/images/bg_02.png', count: 0 },
    { url: '/images/bg_03.png', count: 0 },
    { url: '/images/bg_04.png', count: 0 },
    { url: '/images/bg_05.png', count: 0 },
  ]
  // 控制遮罩的显隐
  @State maskOpacity: number = 0 // 透明度
  @State maskIndex: number = -1; // 显示层级
  // 控制遮罩层图片的缩放
  @State maskImgScaleX: number = 0 // 水平缩放比
  @State maskImgScaleY: number = 0 // 垂直缩放比
  // 获取遮罩层选择的图片Index
  @State maskImgIndex: number = 0

  build() {
    Stack() {
      // 抽卡层
      Column() {
        Grid() {
          ForEach(this.images, (item: ImageCount) => {
            GridItem() {
              Badge({
                count: item.count,
                position: BadgePosition.RightTop,
                style: {
                  fontSize: 12,
                  badgeSize: 16
                }
              }) {
                Image(item.url)
                  .width(80)
              }
            }
          })
        }
        .rowsTemplate('1fr 1fr')
        .columnsTemplate('1fr 1fr 1fr')
        .height(300)
        .margin({ top: 50, bottom: 50 })

        // .backgroundColor(Color.Pink)

        Button('立即抽卡')
          .width(200)
          .backgroundColor('#ED5B8C')
          .onClick(() => {
            // 点击时,修改遮罩参数,让遮罩显示
            this.maskOpacity = 1
            this.maskIndex = 99
            // 点击时修改遮罩层图片的缩放比
            this.maskImgScaleX = 1
            this.maskImgScaleY = 1
            //   // 随机获取图片的Index
            this.maskImgIndex = Math.floor(Math.random() * 6)
          })
      }

      // 遮罩层
      Column({ space: 30 }) {
        Text('获得生肖卡')
          .fontColor('#F3EAD3')
          .fontWeight(700)
          .fontSize(24)

        Image(`/images/img_0${this.maskImgIndex}.png`)
          .width(200)
          .scale({
            //控制图片的缩放
            x: this.maskImgScaleX,
            y: this.maskImgScaleY
          })
          .animation({
            // 动画
            duration: 500
          })

        Button('开心收下')
          .width(200)
          .border({
            width: 2,
            color: '#9F9C90',
          })
          .backgroundColor(Color.Transparent)
          .onClick(() => {
            // 点击时,修改遮罩参数,让遮罩隐藏
            this.maskOpacity = 0
            this.maskIndex = -1
            //   // 点击时修改遮罩层图片的缩放比为1:1
            this.maskImgScaleX = 0
            this.maskImgScaleY = 0
          //   开心收下
            this.images[this.maskImgIndex] = {
              url: `/images/img_0${this.maskImgIndex}.png`,
              count: this.images[this.maskImgIndex].count + 1
            }
          })
      }
      .zIndex(this.maskIndex)
      .opacity(this.maskOpacity)
      .backgroundColor('#cc000000')
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)

      // 抽大奖遮罩层
      Column({space: 30}) {
        Text('恭喜获得手机一部')
          .fontColor('#E4DDC7')
          .fontWeight(700)
          .fontSize(25)
        Image('/images/hw.png')
          .width(300)
        Button('再来一次')
          .width(200)
          .height(50)
          .border({
            width: 2,
            color: '#E4DDC7'
          })
          .backgroundColor(Color.Transparent)
      }
      .justifyContent(FlexAlign.Center)
      .width('100%')
      .height('100%')
      .backgroundColor('#cc000000')

    }
  }
}

抽大奖遮罩层的显隐

前提:

六张卡片集齐,显示 --- 中大奖页面

默认为 false,不显示此抽大奖遮罩层

判断数组项的count, 是否都大于0, 只能有一个等于0,就意味着没及其

最终效果演示

随机奖品 & 再来一次

奖品随机抽 -》准备一个奖品数组, Math

再来一次 -》重置数据

奖品随机抽

准备奖品数组,默认抽中的奖品为空

准备随机数

在“”开心收下“”按钮下,判断是否中奖,如果中奖了,准备抽奖。

效果:

再来一次

将数据重置

效果演示:

完整代码:

import { trustedAppService } from '@kit.DeviceSecurityKit';

// 定义图片接口
interface ImageCount {
  url: ResourceStr,
  count: number
}

@Entry
  @Component
  struct Index {
    // 定义图片渲染数组
    @State images: ImageCount[] = [
      { url: '/images/bg_00.png', count: 0 },
      { url: '/images/bg_01.png', count: 0 },
      { url: '/images/bg_02.png', count: 0 },
      { url: '/images/bg_03.png', count: 0 },
      { url: '/images/bg_04.png', count: 0 },
      { url: '/images/bg_05.png', count: 0 },
    ]
    // 奖品池
    @State prizePool: string[] = [
      '/images/pg.png',
      '/images/hw.png',
      '/images/xm.png'
    ]
    //抽中的奖品
    @State prize: string = '' // 默认没中奖
    // 控制遮罩的显隐
    @State maskOpacity: number = 0 // 透明度
    @State maskIndex: number = -1; // 显示层级
    // 控制遮罩层图片的缩放
    @State maskImgScaleX: number = 0 // 水平缩放比
    @State maskImgScaleY: number = 0 // 垂直缩放比
    // 获取遮罩层选择的图片Index
    @State maskImgIndex: number = 0
    // 控制中大奖的显隐
    @State isGet: boolean = false // 中大奖显隐

    build() {
      Stack() {
        // 抽卡层
        Column() {
          Grid() {
            ForEach(this.images, (item: ImageCount) => {
              GridItem() {
                Badge({
                  count: item.count,
                  position: BadgePosition.RightTop,
                  style: {
                    fontSize: 12,
                    badgeSize: 16
                  }
                }) {
                  Image(item.url)
                    .width(80)
                }
              }
            })
          }
          .rowsTemplate('1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr')
            .height(300)
            .margin({ top: 50, bottom: 50 })

          // .backgroundColor(Color.Pink)

          Button('立即抽卡')
            .width(200)
            .backgroundColor('#ED5B8C')
            .onClick(() => {
              // 点击时,修改遮罩参数,让遮罩显示
              this.maskOpacity = 1
              this.maskIndex = 99
              // 点击时修改遮罩层图片的缩放比
              this.maskImgScaleX = 1
              this.maskImgScaleY = 1
              //   // 随机获取图片的Index
              this.maskImgIndex = Math.floor(Math.random() * 6)
            })
        }

        // 遮罩层
        Column({ space: 30 }) {
          Text('获得生肖卡')
            .fontColor('#F3EAD3')
            .fontWeight(700)
            .fontSize(24)

          Image(`/images/img_0${this.maskImgIndex}.png`)
            .width(200)
            .scale({
              //控制图片的缩放
              x: this.maskImgScaleX,
              y: this.maskImgScaleY
            })
            .animation({
              // 动画
              duration: 500
            })

          Button('开心收下')
            .width(200)
            .border({
              width: 2,
              color: '#9F9C90',
            })
            .backgroundColor(Color.Transparent)
            .onClick(() => {
              // 点击时,修改遮罩参数,让遮罩隐藏
              this.maskOpacity = 0
              this.maskIndex = -1
              //   // 点击时修改遮罩层图片的缩放比为1:1
              this.maskImgScaleX = 0
              this.maskImgScaleY = 0
              //   开心收下
              this.images[this.maskImgIndex] = {
                url: `/images/img_0${this.maskImgIndex}.png`,
              count: this.images[this.maskImgIndex].count + 1
            }
            // 每次收完,要进行简单检索,判断是否集齐
            // 需求:判断数组项的count, 是否都大于0, 只能有一个等于0,就意味着没及其
            let flag: boolean = true // 假设集齐
            // 验证是否集齐
            for (let item of this.images) {
              if (item.count === 0) {
                flag = false // 没集齐
                break; // 只要没集齐,便可退出循环
              }
            }
            this.isGet = flag
            if (flag) {
              let randIndex: number = Math.floor(Math.random() * 3)
              this.prize = this.prizePool[randIndex]
            }
          })
      }
      .zIndex(this.maskIndex)
      .opacity(this.maskOpacity)
      .backgroundColor('#cc000000')
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)

      // 抽大奖遮罩层
      if (this.isGet) {
        Column({ space: 30 }) {
          Text('恭喜获得手机一部')
            .fontColor('#E4DDC7')
            .fontWeight(700)
            .fontSize(25)
          Image(this.prize)
            .width(300)
          Button('再来一次')
            .width(200)
            .height(50)
            .border({
              width: 2,
              color: '#E4DDC7'
            })
            .backgroundColor(Color.Transparent)
            .onClick(() => {
              this.isGet = false
              this.prize = ''
              this.images = [
                { url: '/images/bg_00.png', count: 0 },
                { url: '/images/bg_01.png', count: 0 },
                { url: '/images/bg_02.png', count: 0 },
                { url: '/images/bg_03.png', count: 0 },
                { url: '/images/bg_04.png', count: 0 },
                { url: '/images/bg_05.png', count: 0 },
              ]
            })
        }
        .justifyContent(FlexAlign.Center)
        .width('100%')
        .height('100%')
        .backgroundColor('#cc000000')
      }
    }
  }
}

相关文章:

  • 24.0.2 双系统ubuntu 安装显卡驱动黑屏,系统启动界面键盘失灵
  • 跨站点请求伪造(CSRF)原理与Spring Security防护机制详解
  • 数据结构|排序算法(二)插入排序 希尔排序 冒泡排序
  • gerrit上面可以git fetch
  • P8697 [蓝桥杯 2019 国 C] 最长子序列
  • conda-pack打包环境到超算上。解决无法打包可编辑包
  • GIS开发笔记(3)win11环境中osgearth加载大体积全球高程数据(dem)
  • 以太网供电(PoE)交换机:为音频和视频系统赋能的多面利器
  • 探索安固软件:保护您的电子文档安全
  • 探秘 MQTT 协议:物联网的 “隐形桥梁”
  • Java面试43-常见的限流算法有哪些?
  • MySQL5.7数据库部署和安装
  • cesium项目之cesiumlab地形数据加载
  • 设计模式:依赖倒转原则 - 依赖抽象,解耦具体实现
  • UI测试流程与关键注意点解析
  • LLMs基础学习(七)DeepSeek专题(1)
  • 我的计算机网络(总览篇)
  • BERT - MLM 和 NSP
  • 2025最新数字化转型国家标准《数字化转型管理参考架构》 正式发布
  • 蓝桥杯python组备考3(b站课程笔记)超详细
  • 小微企业做网站/苏州百度推广分公司电话
  • 网站的花费/百度首页登录官网
  • wordpress更换域名搬家/1688seo优化是什么
  • 站长工具是什么/成都高薪seo
  • 元旦ppt模板免费下载/seo优化工具大全
  • 门户网站建设需要注意什么/seo推广经验