在 HarmonyOS 生态快速发展的今天,ArkTS 作为鸿蒙应用开发的核心语言,凭借声明式 UI、状态管理、组件化开发等优势,成为前端开发者、鸿蒙开发者的必备技能。对于初学者而言,通过实战项目掌握 ArkTS 的核心语法和开发逻辑,是最高效的学习方式。
本文将带你从零开始,使用ArkTS + 声明式 UI 开发一个完整的生肖集卡抽奖小程序,实现随机抽卡、卡片计数、集齐卡片自动抽奖、大奖弹窗、重置游戏等核心功能。项目覆盖了 ArkTS 接口定义、状态管理、循环渲染、动画效果、条件渲染、事件绑定等高频知识点,全程可直接运行、可扩展优化,适合鸿蒙开发入门学习和实战参考。
项目最终效果:
- 首页展示 6 个生肖卡片格子,默认显示背景图,右上角徽章展示卡片数量;
- 点击「立即抽卡」弹出抽卡弹窗,随机生成一张生肖卡片,带动画缩放效果;
- 点击「开心收下」关闭弹窗,对应生肖卡片计数 + 1,更新显示;
- 集齐 6 张不同生肖卡后,自动触发大奖抽奖,随机弹出奖品弹窗;
- 奖品弹窗点击「再来一次」重置所有卡片和状态,重新开始游戏。
一、项目开发环境准备
1. 开发工具
本项目基于DevEco Studio (鸿蒙官方 IDE)开发,版本建议使用DevEco Studio 3.1 及以上,支持 ArkTS 语法、预览器、真机 / 模拟器调试。
2. 基础配置
- 新建Stage 模型ArkTS 工程,选择 Empty Ability 模板;
- 将项目所需图片资源(背景图
bg_00~bg_05、生肖卡img_00~img_05、奖品图pg/hw/xm)放入main_pages/src/main/resources/base/media目录; - 入口文件为
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堆叠容器,分为三层:
- 底层:生肖卡片宫格 + 抽卡按钮;
- 中层:抽卡弹窗(默认隐藏);
- 顶层:大奖弹窗(集齐卡片后显示)。
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%')
核心逻辑解析:
- Grid 网格布局 :通过
columnsTemplate和rowsTemplate设置 2 行 3 列,完美适配 6 张卡片; - ForEach 循环渲染 :遍历
images数组,批量生成卡片格子,无需重复编写 6 个 GridItem; - Badge 徽章组件 :绑定卡片
count值,右上角实时显示卡片持有数量; - 按钮点击事件:点击后修改弹窗状态(显示)、触发动画、生成随机卡片索引。
步骤 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 }) // 弹窗显隐动画
核心逻辑解析:
- 动态图片渲染 :通过模板字符串
img_0${this.randomIndex},根据随机索引渲染对应生肖卡片; - 缩放动画 :
scale结合animation,实现卡片弹出的缩放效果,提升交互体验; - 数组对象更新 :ArkTS 中数组内对象变更需整体替换 才能触发 UI 刷新,因此直接修改
images[index]对象; - 集齐校验逻辑 :遍历所有卡片,若所有
count>0则判定为集齐,触发大奖状态; - 随机抽奖 :集齐后从奖品数组中随机抽取一个奖品,赋值给
prizeIndex。
步骤 4:实现大奖弹窗与游戏重置
当prize为true时,条件渲染大奖弹窗,展示奖品图片和「再来一次」按钮,点击后重置所有状态,重新开始游戏。
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')
}
}
}
}
核心逻辑解析:
- 条件渲染 :
if (this.prize)控制弹窗只在集齐卡片时显示; - 动态奖品 :根据
prizeIndex渲染对应奖品图片; - 游戏重置:点击按钮后,清空大奖状态、奖品索引,将卡片数组恢复为初始值,实现重新游戏。
至此,完整的生肖集卡抽奖小程序代码就全部实现了!
四、项目运行与效果测试
1. 运行方式
- 连接鸿蒙模拟器或真机;
- 点击 DevEco Studio 右上角「运行」按钮;
- 等待应用安装启动,即可在设备上测试功能。
2.运行结果
点击'立即抽奖'按钮,弹出随机生肖卡,点击'开心收下',就会出现图三显示
还可以再点击'立即抽奖'按钮,再次抽卡



五、ArkTS 开发核心总结
通过这个生肖集卡抽奖项目,我们可以总结出 ArkTS 开发的核心思想:
1. 声明式 UI:数据驱动视图
无需手动操作 DOM,只需要修改@State状态变量,UI 自动刷新,极大简化开发流程。
2. 组件化:复用与拆分
所有 UI 都是组件,容器组件负责布局,基础组件负责展示,拆分清晰,易于维护。
3. 状态管理:@State 是核心
页面交互的核心就是状态管理,明确状态的定义、修改、触发刷新的逻辑,就能搞定大部分交互功能。
4. 动画与交互:提升体验
ArkTS 内置animation、scale、translate等动画属性,几行代码就能实现流畅的交互效果。
5. 数组 / 对象更新规则
数组内对象变更必须整体替换才能触发 UI 刷新,这是 ArkTS 初学者最容易踩的坑。
七、结语
本文通过一个完整的生肖集卡抽奖小程序,带你从零掌握 HarmonyOS ArkTS 声明式开发的核心技能,涵盖了接口定义、状态管理、布局组件、循环 / 条件渲染、事件绑定、动画效果等全量知识点。项目代码简洁、逻辑清晰,既适合入门学习,也可以作为鸿蒙实战项目的基础模板二次开发。
鸿蒙生态的发展前景广阔,ArkTS 作为核心开发语言,是未来跨设备、跨平台开发的趋势。希望通过这个实战项目,能让你快速入门鸿蒙开发,激发你的创作灵感。后续可以基于本项目继续扩展功能,打造属于自己的鸿蒙应用!
如果需要进一步学习 ArkTS 高级特性(如自定义组件、数据持久化、网络请求、跨设备通信等),可以持续关注鸿蒙官方文档和实战教程,循序渐进提升开发能力