
【引言】
在鸿蒙NEXT开发中,九宫格抽奖是一个常见且有趣的应用场景。通过九宫格抽奖,用户可以随机获得不同奖品,增加互动性和趣味性。本文将介绍如何使用鸿蒙开发框架实现九宫格抽奖功能,并通过代码解析展示实现细节。
【环境准备】
• 操作系统:Windows 10
• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
• 目标设备:华为Mate60 Pro
• 开发语言:ArkTS
• 框架:ArkUI
• API版本:API 12
【思路】
1. 奖品类定义
首先,我们定义了一个Prize类,用于表示每个奖品的信息,包括标题、颜色和描述。通过构造函数初始化奖品信息,为后续抽奖功能提供数据支持。
2. 抽奖页面结构
在抽奖页面结构中,我们使用了鸿蒙的组件化开发方式,定义了一个LotteryPage组件。该组件包含了抽奖所需的状态变量、抽奖顺序数组、奖品数组以及抽奖逻辑的实现方法。
3. 抽奖逻辑实现
九宫格抽奖的逻辑主要包括三个阶段:加速、匀速和减速。通过startLottery方法开始抽奖并逐渐加速,然后进入runAtConstantSpeed方法以恒定速度运行抽奖,最后通过slowDown方法减速并展示抽奖结果。
4. 构建UI界面
在构建UI界面时,我们使用了鸿蒙的布局组件和样式设置,将奖品以九宫格形式展示在页面上。每个奖品格子都可以点击,点击抽奖按钮后会触发抽奖动画,展示抽奖结果对话框。
【完整代码】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
class
Prize {
title: string
// 奖品标题
color: string
// 奖品颜色
description: string
// 奖品描述
constructor(title: string, color: string, description: string =
""
) {
// 构造函数,初始化奖品信息
this
.title = title
// 设置奖品标题
this
.color = color
// 设置奖品颜色
this
.description = description
// 设置奖品描述
}
}
// 九宫格抽奖图
@Entry
// 入口注解,标识这是一个可启动的组件
@Component
// 组件注解,标识这是一个组件
struct LotteryPage {
// 定义抽奖页面结构
@State selectedIndex: number = 0
// 当前选中的索引,初始为0
private
isAnimating: boolean =
false
// 是否正在进行动画,初始为false
private
selectionOrder: number[] = [0, 1, 2, 5, 8, 7, 6, 3]
// 抽奖顺序数组
private
cellWidth: number = 200
// 单元格宽度
private
baseMargin: number = 10
// 单元格边距
private
prizeArray: Prize[] = [
// 奖品数组
new
Prize(
"红包"
,
"#ff9675"
,
"10元"
),
// 创建奖品对象
new
Prize(
"话费"
,
"#ff9f2e"
,
"5元"
),
new
Prize(
"红包"
,
"#8e7fff"
,
"50元"
),
new
Prize(
"红包"
,
"#48d1ea"
,
"30元"
),
new
Prize(
"开始\n抽奖"
,
"#fffdfd"
),
// 抽奖按钮
new
Prize(
"谢谢参与"
,
"#5f5f5f"
),
// 参与提示
new
Prize(
"谢谢参与"
,
"#5f5f5f"
),
new
Prize(
"超市红包"
,
"#5f5f5f"
,
"100元"
),
new
Prize(
"鲜花"
,
"#75b0fe"
),
// 奖品对象
]
private
intervalID: number = 0
// 定时器ID,用于控制抽奖速度
startLottery(speed: number = 500) {
// 开始抽奖,默认速度为500毫秒
setTimeout(() => {
// 设置延时执行
if
(speed > 50) {
// 如果速度大于50
speed -= 50
// 减少速度
this
.startLottery(speed)
// 递归调用,继续加速
}
else
{
this
.runAtConstantSpeed()
// 速度达到阈值,进入匀速阶段
return
}
this
.selectedIndex++
// 更新选中的索引
}, speed)
// 延迟时间为当前速度
}
runAtConstantSpeed() {
// 以恒定速度运行抽奖
let
speed = 40 + Math.floor(Math.random() *
this
.selectionOrder.length)
// 随机生成速度
clearInterval(
this
.intervalID)
// 清除之前的定时器
this
.intervalID = setInterval(() => {
// 设置新的定时器
if
(
this
.selectedIndex >= speed) {
// 如果选中索引达到速度
clearInterval(
this
.intervalID)
// 清除定时器
this
.slowDown()
// 进入减速阶段
return
}
this
.selectedIndex++
// 更新选中的索引
}, 50)
// 每50毫秒更新一次
}
slowDown(speed = 50) {
// 减速,默认速度为50毫秒
setTimeout(() => {
// 设置延时执行
if
(speed < 500) {
// 如果速度小于500
speed += 50
// 增加速度
this
.slowDown(speed)
// 递归调用,继续减速
}
else
{
this
.selectedIndex =
this
.selectedIndex %
this
.selectionOrder.length
// 确保索引在范围内
let
index =
this
.selectionOrder[
this
.selectedIndex]
// 获取当前选中的奖品索引
this
.isAnimating =
false
// 动画结束,设置为false
this
.getUIContext().showAlertDialog({
// 显示结果对话框
title:
'结果'
,
// 对话框标题
message: `${
this
.prizeArray[index].title}${
this
.prizeArray[index].description}`,
// 显示奖品信息
confirm: {
// 确认按钮配置
defaultFocus:
true
,
// 默认聚焦
value:
'我知道了'
,
// 按钮文本
action: () => {
// 按钮点击事件
}
},
alignment: DialogAlignment.Center,
// 对话框居中显示
});
return
}
this
.selectedIndex++
// 更新选中的索引
}, speed)
// 延迟时间为当前速度
}
build() {
// 构建UI
Column() {
// 使用列布局
Flex({ wrap: FlexWrap.Wrap }) {
// 使用弹性布局,允许换行
ForEach(
this
.prizeArray, (item: Prize, index: number) => {
// 遍历奖品数组
Column() {
// 每个奖品使用列布局
Text(`${item.title}`)
// 显示奖品标题
.fontColor(
this
.selectionOrder[
this
.selectedIndex %
this
.selectionOrder.length] == index ? Color.White :
// 根据选中状态设置字体颜色
item.color)
.fontSize(16)
// 设置字体大小
Text(`${item.description}`)
// 显示奖品描述
.fontColor(
this
.selectionOrder[
this
.selectedIndex %
this
.selectionOrder.length] == index ? Color.White :
// 根据选中状态设置字体颜色
item.color)
.fontSize(20)
// 设置字体大小
}
.clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 })
// 点击效果
.onClick(() => {
// 点击事件处理
if
(index == 4) {
// 如果点击的是抽奖按钮
if
(
this
.isAnimating) {
// 如果正在动画中,返回
return
}
this
.isAnimating =
true
// 设置为正在动画
this
.startLottery()
// 开始抽奖
}
})
.alignItems(HorizontalAlign.Center)
// 水平居中对齐
.justifyContent(FlexAlign.Center)
// 垂直居中对齐
.width(`${
this
.cellWidth}lpx`)
// 设置单元格宽度
.height(`${
this
.cellWidth}lpx`)
// 设置单元格高度
.margin(`${
this
.baseMargin}lpx`)
// 设置单元格边距
.backgroundColor(index == 4 ?
"#ff5444"
:
// 设置背景颜色,抽奖按钮为特殊颜色
(
this
.selectionOrder[
this
.selectedIndex %
this
.selectionOrder.length] == index ? Color.Gray : Color.White))
// 根据选中状态设置背景颜色
.borderRadius(10)
// 设置圆角
.shadow({
// 设置阴影效果
radius: 10,
// 阴影半径
color:
"#f98732"
,
// 阴影颜色
offsetX: 0,
// 水平偏移
offsetY: 20
// 垂直偏移
})
})
}.width(`${
this
.cellWidth * 3 +
this
.baseMargin * 6}lpx`)
// 设置整体宽度
.margin({ top: 30 })
// 设置顶部边距
}
.height(
'100%'
)
// 设置高度为100%
.width(
'100%'
)
// 设置宽度为100%
.backgroundColor(
"#ffb350"
)
// 设置背景颜色
}
}
|
原创作者: zhongcx 转载于: https://www.cnblogs.com/zhongcx/p/18602222