前言
UI方面:整体为Stack布局,里面的布局方面是多种多样的,组件使用了Badge组件把人物包起来,这样就可以实现角标的效果,此外还使用了动画animation属性方法,使得当顶层页面跳出时更加顺滑
TS方面:使用随机数(Math.random)方法来实现随机抽卡的逻辑,然后集齐所有的卡即可兑换神卡,如果有想玩黑神话悟空的bro,祝你们玩的开心,因为我的电脑带不动,只能等换电脑再玩了
这个案例也是跟着黑马敲的
效果
页面能看即可doge
代码
interface ImageCount {
url: string
count: number
name: string
}
//遮掩层显隐,opacity 0-1,层级index -1-99
//图片缩放 scale 0-1
@Entry
@Component
struct stringDemo {
@State images: ImageCount[] = [
{ url: 'app.media.zfb_mine', count: 0, name: '孙悟空' },
{ url: 'app.media.zfb_mine', count: 0, name: '猪八戒' },
{ url: 'app.media.zfb_mine', count: 0, name: '沙僧' },
{ url: 'app.media.zfb_mine', count: 0, name: '白龙马' },
{ url: 'app.media.zfb_mine', count: 0, name: '二郎神' },
{ url: 'app.media.zfb_mine', count: 0, name: '如来佛祖' }
]
//控制遮掩层的透明度和显示优先级
@State maskOpacity: number = 0
@State maskZIndex: number = -1
//控制图片的X轴和Y轴的缩放比例
@State maskImageX: number = 0
@State maskImageY: number = 0
//生成随机数下标
@State randomIndex: number = 1
//控制中大奖的显影
@State isGet: boolean = false
build() {
Stack() {
//初始化网格布局
Column() {
Grid() {
ForEach(this.images, (item: ImageCount, index) => {
GridItem() {
Column() {
Badge({
count: item.count,
position: BadgePosition.RightTop, //角标位置
style: {
fontSize: 14,
badgeSize: 20,
badgeColor: '#FA2A2D'
}
}) {
Image($r(item.url))
.height(80)
.width(80)
}
Text(item.name)
.width(60)
.margin({ top: 5 })
.textAlign(TextAlign.Center)
}
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.width('100%')
.height(300)
.margin({ top: 100 })
Button('抽卡')
.width(200)
.backgroundColor('#eb5b8c')
.margin(50)
.onClick(() => {
//点击时,改变遮掩层的opacity和zindex
this.maskOpacity = 1
this.maskZIndex = 99
//图片缩放
this.maskImageX = 1
this.maskImageY = 1
//计算随机数,选择要抽到的卡
this.randomIndex = Math.floor(Math.random() * 6)
})
}
.width('100%')
.height('100%')
.backgroundColor(Color.Pink)
//抽卡遮掩图
Column() {
Text('抽中了')
.fontColor('#f5ebcf')
.fontSize(25)
.fontWeight(FontWeight.Bold)
Image($r(this.images[0].url))
.width(200)
.fillColor(Color.White)//控制图片的缩放
.scale({
x: this.maskImageX, y: this.maskImageY
})
.animation({
duration: 100
})
Text(this.images[this.randomIndex].name)
.width(60)
.textAlign(TextAlign.Center)
.fontColor('#fff9e0')
Button('就选你了')
.width(200)
.height(50)
.backgroundColor(Color.Transparent)
.border({ width: 2, color: '#fff9e0' })
.margin({ top: 10 })
.onClick(() => {
this.maskOpacity = 0
this.maskZIndex = -1
//重置缩放
this.maskImageX = 0
this.maskImageY = 0
//右红标加一,如果是对象数组需要更新,需要修改替换整个对象
// this.images[this.randomIndex].count++
this.images[this.randomIndex] = {
url: this.images[this.randomIndex].url,
count: this.images[this.randomIndex].count + 1,
name: this.images[this.randomIndex].name
}
//每次收卡,都要判断
let flag: boolean = true
for (let item of this.images) {
if (item.count == 0) {
flag = false
break
}
}
this.isGet = flag
})
}
.width('100%')
.height('100%')
.backgroundColor('#cc000000')
.justifyContent(FlexAlign.Center)
.opacity(this.maskOpacity)
.zIndex(this.maskZIndex)
//动画
.animation({
duration: 100
})
if (this.isGet) {
//抽大奖的遮掩层
Column({ space: 30 }) {
Text('迎接你们的王')
.fontColor('#f5ebcf')
.fontSize(25)
.fontWeight(700)
Image($r(this.images[0].url))
.fillColor(Color.White)
.width(300)
Text(`神·${this.images[0].name}`)
.fontColor('#f5ebcf')
.fontSize(25)
.fontWeight(700)
Button('继续抽奖')
.width(200)
.height(50)
.backgroundColor(Color.Transparent)
.border({ width: 2, color: '#fff9e0' })
.onClick(() => {
this.isGet = false
this.images = [{ url: 'app.media.zfb_mine', count: 0, name: '孙海军' },
{ url: 'app.media.zfb_mine', count: 0, name: '潘玉鹏' },
{ url: 'app.media.zfb_mine', count: 0, name: '张子隆' },
{ url: 'app.media.zfb_mine', count: 0, name: '鲁玉' },
{ url: 'app.media.zfb_mine', count: 0, name: '变祁隆' },
{ url: 'app.media.zfb_mine', count: 0, name: '曹远征' }]
})
}
.width('100%')
.height('100%')
.backgroundColor('#cc000000')
.justifyContent(FlexAlign.Center)
.animation({
duration: 200
})
}
}
}
}