HarmonyOS 鸿蒙 ArkTS 实战:从零开发生肖集卡抽奖小程序

在 HarmonyOS 生态快速发展的今天,ArkTS 作为鸿蒙应用开发的核心语言,凭借声明式 UI、状态管理、组件化开发等优势,成为前端开发者、鸿蒙开发者的必备技能。对于初学者而言,通过实战项目掌握 ArkTS 的核心语法和开发逻辑,是最高效的学习方式。

本文将带你从零开始,使用ArkTS + 声明式 UI 开发一个完整的生肖集卡抽奖小程序,实现随机抽卡、卡片计数、集齐卡片自动抽奖、大奖弹窗、重置游戏等核心功能。项目覆盖了 ArkTS 接口定义、状态管理、循环渲染、动画效果、条件渲染、事件绑定等高频知识点,全程可直接运行、可扩展优化,适合鸿蒙开发入门学习和实战参考。

项目最终效果:

  1. 首页展示 6 个生肖卡片格子,默认显示背景图,右上角徽章展示卡片数量;
  2. 点击「立即抽卡」弹出抽卡弹窗,随机生成一张生肖卡片,带动画缩放效果;
  3. 点击「开心收下」关闭弹窗,对应生肖卡片计数 + 1,更新显示;
  4. 集齐 6 张不同生肖卡后,自动触发大奖抽奖,随机弹出奖品弹窗;
  5. 奖品弹窗点击「再来一次」重置所有卡片和状态,重新开始游戏。

一、项目开发环境准备

1. 开发工具

本项目基于DevEco Studio (鸿蒙官方 IDE)开发,版本建议使用DevEco Studio 3.1 及以上,支持 ArkTS 语法、预览器、真机 / 模拟器调试。

2. 基础配置

  1. 新建Stage 模型ArkTS 工程,选择 Empty Ability 模板;
  2. 将项目所需图片资源(背景图bg_00~bg_05、生肖卡img_00~img_05、奖品图pg/hw/xm)放入main_pages/src/main/resources/base/media目录;
  3. 入口文件为Index.ets,所有代码均在该文件中实现。

3. 核心技术栈

  • ArkTS 声明式 UI 语法
  • 组件状态管理(@State 装饰器)
  • 容器组件(Stack/Column/Grid/GridItem)
  • 基础组件(Image/Button/Text/Badge)
  • 动画效果(animation/scale)
  • 循环渲染(ForEach)
  • 条件渲染(if)
  • 自定义接口(interface)

二、核心知识点前置讲解

在编写代码前,我们先梳理项目中用到的核心 ArkTS 知识点,帮助你理解代码逻辑:

1. 自定义接口(interface)

interface 用于定义对象的类型规范,约束对象的属性和类型,提升代码可读性和健壮性。本项目中用于规范卡片数据结构。

2. @State 状态装饰器

@State 修饰的变量为响应式状态,当变量值发生改变时,UI 会自动刷新渲染,是 ArkTS 状态管理的核心。

3. 容器组件

  • Stack:堆叠容器,子组件按编写顺序堆叠,适合实现弹窗覆盖效果;
  • Column:垂直布局容器,默认子组件垂直排列;
  • Grid/GridItem:网格布局容器,用于实现卡片宫格效果。

4. 循环渲染 ForEach

用于遍历数组,批量渲染组件,简化重复代码,本项目用于渲染 6 个生肖卡片格子。

5. 条件渲染 if

根据布尔值状态决定组件是否显示,本项目用于控制抽卡弹窗、大奖弹窗的显隐。

6. 动画与样式

  • animation:为状态变化添加过渡动画;
  • scale:缩放属性,实现卡片弹出动画;
  • opacity/zIndex:控制透明度和层级,实现弹窗遮罩效果。

三、项目代码分步实现

步骤 1:定义数据接口与响应式状态

首先我们定义ImageCount接口,规范卡片对象的结构:包含图片路径url和卡片计数count

然后通过@State定义所有响应式变量,包括:奖品数组、随机卡片索引、弹窗显隐控制、动画参数、游戏状态等。所有状态变更都会自动驱动 UI 刷新。

TypeScript 复制代码
// 定义卡片数据接口,约束对象结构
interface ImageCount{
  url:string   // 图片资源路径
  count:number // 卡片持有数量
}

@Entry
@Component
struct Index {
  // 奖品列表:苹果、华为、小米
  @State prizes:string[]=['pg','hw','xm']
  // 中奖奖品索引
  @State prizeIndex:string='' 
  // 随机生肖卡索引(0-5),-1表示未抽卡
  @State randomIndex:number = -1 
  // 卡片数据数组,6个生肖卡片
  @State images:ImageCount[]=[
    {url:'app.media.bg_00',count:0},
    {url:'app.media.bg_01',count:0},
    {url:'app.media.bg_02',count:0},
    {url:'app.media.bg_03',count:0},
    {url:'app.media.bg_04',count:0},
    {url:'app.media.bg_05',count:0}
  ]
  // 遮罩层透明度:0隐藏,1显示
  @State maskOpacity:number = 0
  // 遮罩层层级:-1底层,99顶层
  @State maskzIndex:number = -1
  // 卡片缩放动画参数
  @State maskImageX:number = 0
  @State maskImageY:number = 0
  // 大奖弹窗显隐控制
  @State prize:boolean = false

步骤 2:搭建主页面布局(Stack 堆叠容器)

整个页面使用Stack堆叠容器,分为三层:

  1. 底层:生肖卡片宫格 + 抽卡按钮;
  2. 中层:抽卡弹窗(默认隐藏);
  3. 顶层:大奖弹窗(集齐卡片后显示)。
TypeScript 复制代码
  build() {
    Stack() { // 堆叠容器,实现弹窗覆盖效果
      // 1. 主页面:卡片宫格 + 抽卡按钮
      Column() {
        // 网格布局:2行3列展示6张卡片
        Grid() {
          // 循环渲染卡片
          ForEach(this.images, (item: ImageCount, index: number) => {
            GridItem() {
              // 徽章组件:右上角显示卡片数量
              Badge({
                count: item.count,
                position: BadgePosition.RightTop,
                style: {
                  fontSize: 14,
                  badgeSize: 20,
                  badgeColor: '#fa2a2d'
                }
              }) {
                Image($r(item.url))
                  .width(70)
              }
            }
          })
        }
        .columnsTemplate('1fr 1fr 1fr') // 3列
        .rowsTemplate('1fr 1fr')         // 2行
        .width('100%')
        .height(300)

        // 抽卡按钮
        Button('立即抽卡')
          .onClick(() => {
            // 显示抽卡弹窗
            this.maskOpacity = 1
            this.maskzIndex = 99
            // 触发卡片缩放动画
            this.maskImageX = 1
            this.maskImageY = 1
            // 生成0-5随机数,对应生肖卡片
            this.randomIndex = Math.floor(Math.random() * 6)
          })
          .width(200)
          .backgroundColor('#1d5b8c')
          .margin({ top: 50 })
      }
      .width('100%')
      .height('100%')
核心逻辑解析:
  1. Grid 网格布局 :通过columnsTemplaterowsTemplate设置 2 行 3 列,完美适配 6 张卡片;
  2. ForEach 循环渲染 :遍历images数组,批量生成卡片格子,无需重复编写 6 个 GridItem;
  3. Badge 徽章组件 :绑定卡片count值,右上角实时显示卡片持有数量;
  4. 按钮点击事件:点击后修改弹窗状态(显示)、触发动画、生成随机卡片索引。

步骤 3:实现抽卡弹窗与收下逻辑

抽卡弹窗为半透明遮罩层,包含标题、随机生肖卡片、「开心收下」按钮。核心功能:动画效果、计数更新、集齐校验

TypeScript 复制代码
      // 2. 抽卡遮罩层(中层)
      Column({ space: 30 }) {
        Text('获得生肖卡')
          .fontColor('#f5ebcf')
          .fontSize(30)
          .fontWeight(700)
        // 动态渲染随机抽到的生肖卡片
        Image($r(`app.media.img_0${this.randomIndex}`))
          .width(200)
          .scale({ x: this.maskImageX, y: this.maskImageY }) // 缩放
          .animation({ duration: 500 }) // 动画时长500ms

        // 收下卡片按钮
        Button('开心收下')
          .onClick(() => {
            // 隐藏弹窗
            this.maskOpacity = 0
            this.maskzIndex = -1
            // 重置动画参数
            this.maskImageX = 0
            this.maskImageY = 0

            // 关键:更新卡片计数(数组对象需整体替换)
            this.images[this.randomIndex] = {
              url: `app.media.img_0${this.randomIndex}`,
              count: this.images[this.randomIndex].count + 1
            }

            // 校验是否集齐6张卡片
            let flag:boolean = true 
            for(let item of this.images){
              if (item.count == 0) {
                flag = false
                break 
              }
            }
            this.prize = flag

            // 集齐则随机抽奖
            if(flag){
              let randomIndex:number=Math.floor(Math.random()*3)
              this.prizeIndex = this.prizes[randomIndex]
            }
          })
          .width(200)
          .height(50)
          .backgroundColor(Color.Transparent)
          .border({ width: 2, color: '#fff9e0' })
      }
      .justifyContent(FlexAlign.Center)
      .width('100%')
      .height('100%')
      .backgroundColor('#cc000000') // 半透明黑色遮罩
      .opacity(this.maskOpacity)
      .zIndex(this.maskzIndex)
      .animation({ duration: 300 }) // 弹窗显隐动画
核心逻辑解析:
  1. 动态图片渲染 :通过模板字符串img_0${this.randomIndex},根据随机索引渲染对应生肖卡片;
  2. 缩放动画scale结合animation,实现卡片弹出的缩放效果,提升交互体验;
  3. 数组对象更新 :ArkTS 中数组内对象变更需整体替换 才能触发 UI 刷新,因此直接修改images[index]对象;
  4. 集齐校验逻辑 :遍历所有卡片,若所有count>0则判定为集齐,触发大奖状态;
  5. 随机抽奖 :集齐后从奖品数组中随机抽取一个奖品,赋值给prizeIndex

步骤 4:实现大奖弹窗与游戏重置

prizetrue时,条件渲染大奖弹窗,展示奖品图片和「再来一次」按钮,点击后重置所有状态,重新开始游戏。

TypeScript 复制代码
      // 3. 大奖弹窗(顶层,条件渲染)
      if (this.prize) {
        Column({ space: 30 }) {
          Text('恭喜获得手机一部')
            .fontSize(25)
            .fontColor('#f5ebcf')
            .fontWeight(700)
          // 动态渲染中奖奖品图片
          Image($r(`app.media.${this.prizeIndex}`))
            .width(300)
          // 重置游戏按钮
          Button('再来一次')
            .onClick(()=>{
              this.prize = false
              this.prizeIndex=''
              // 重置所有卡片为初始状态
              this.images=[
                {url:'app.media.bg_00',count:0},
                {url:'app.media.bg_01',count:0},
                {url:'app.media.bg_02',count:0},
                {url:'app.media.bg_03',count:0},
                {url:'app.media.bg_04',count:0},
                {url:'app.media.bg_05',count:0}
              ]
            })
            .width(200)
            .height(50)
            .backgroundColor(Color.Transparent)
            .border({ width: 2, color: '#fff9e0' })
        }
        .justifyContent(FlexAlign.Center)
        .width('100%')
        .height('100%')
        .backgroundColor('#cc000000')
      }
    }
  }
}
核心逻辑解析:
  1. 条件渲染if (this.prize)控制弹窗只在集齐卡片时显示;
  2. 动态奖品 :根据prizeIndex渲染对应奖品图片;
  3. 游戏重置:点击按钮后,清空大奖状态、奖品索引,将卡片数组恢复为初始值,实现重新游戏。

至此,完整的生肖集卡抽奖小程序代码就全部实现了!

四、项目运行与效果测试

1. 运行方式

  1. 连接鸿蒙模拟器或真机;
  2. 点击 DevEco Studio 右上角「运行」按钮;
  3. 等待应用安装启动,即可在设备上测试功能。

2.运行结果

点击'立即抽奖'按钮,弹出随机生肖卡,点击'开心收下',就会出现图三显示

还可以再点击'立即抽奖'按钮,再次抽卡

五、ArkTS 开发核心总结

通过这个生肖集卡抽奖项目,我们可以总结出 ArkTS 开发的核心思想:

1. 声明式 UI:数据驱动视图

无需手动操作 DOM,只需要修改@State状态变量,UI 自动刷新,极大简化开发流程。

2. 组件化:复用与拆分

所有 UI 都是组件,容器组件负责布局,基础组件负责展示,拆分清晰,易于维护。

3. 状态管理:@State 是核心

页面交互的核心就是状态管理,明确状态的定义、修改、触发刷新的逻辑,就能搞定大部分交互功能。

4. 动画与交互:提升体验

ArkTS 内置animationscaletranslate等动画属性,几行代码就能实现流畅的交互效果。

5. 数组 / 对象更新规则

数组内对象变更必须整体替换才能触发 UI 刷新,这是 ArkTS 初学者最容易踩的坑。

七、结语

本文通过一个完整的生肖集卡抽奖小程序,带你从零掌握 HarmonyOS ArkTS 声明式开发的核心技能,涵盖了接口定义、状态管理、布局组件、循环 / 条件渲染、事件绑定、动画效果等全量知识点。项目代码简洁、逻辑清晰,既适合入门学习,也可以作为鸿蒙实战项目的基础模板二次开发。

鸿蒙生态的发展前景广阔,ArkTS 作为核心开发语言,是未来跨设备、跨平台开发的趋势。希望通过这个实战项目,能让你快速入门鸿蒙开发,激发你的创作灵感。后续可以基于本项目继续扩展功能,打造属于自己的鸿蒙应用!

如果需要进一步学习 ArkTS 高级特性(如自定义组件、数据持久化、网络请求、跨设备通信等),可以持续关注鸿蒙官方文档和实战教程,循序渐进提升开发能力

相关推荐
枫叶丹41 小时前
【HarmonyOS 6.0】Data Augmentation Kit端侧问答模型:本地化智能问答的技术演进
开发语言·华为·harmonyos
C雨后彩虹2 小时前
猴子爬山问题
java·数据结构·算法·华为·面试
想你依然心痛2 小时前
HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与Face AR & Body AR的“灵境直播间“——PC端沉浸式AR电商直播工作台
华为·ar·harmonyos·悬浮导航·沉浸光感
枫叶丹42 小时前
【HarmonyOS 6.0】Desktop Extension Kit 正式接棒原状态栏服务,API 引用路径全面更新
开发语言·华为·harmonyos
我是伪码农2 小时前
小程序26-50
小程序
前端不太难3 小时前
鸿蒙 App 的 Task 架构设计
华为·状态模式·harmonyos
HwJack2013 小时前
HarmonyOS APP开发之解密 ArkTS 状态管理:@State, @Observed, @ObjectLink 三角阵
华为·harmonyos
计算机学姐15 小时前
基于微信小程序的图书馆座位预约系统【uniapp+springboot+vue】
vue.js·spring boot·微信小程序·小程序·java-ee·uni-app·intellij-idea
焦糖玛奇朵婷20 小时前
健身房预约小程序开发、设计
java·大数据·服务器·前端·小程序