任務:使用“對象數組”、“ForEach渲染”、“Badge角標組件”、“Grid布局”等相關知識,實現生效抽獎卡案例。如圖1所示:
圖1 生肖抽獎卡實例圖?
圖1(a)中有6張生肖卡可以抽獎,每抽中一張,會通過彈層顯示出來(圖(b)),每抽中一張,圖片的右上角數量增加1,若6張卡片均抽中了(每種卡片至少有一張),就可以抽更大的獎,包括華為、蘋果以及小米三種不同的手機,如圖1(c)。也可實現支付寶集五福案例,功能相似即可。
參考資料:68-【階段綜合】-生肖抽卡-Badge角標組件_嗶哩嗶哩_bilibili
實驗過程:
????????首先,定義了一個接口`Images`,用于描述每張生肖卡的數據結構,包含圖片的URL和數量(`count`)。接著,基于這個接口準備了初始數據,即6張生肖卡,每張卡的初始數量為0。
????????在頁面布局方面,使用了`Stack`層疊布局來實現頁面的多層顯示。最底層是一個`Column`布局,其中包含了一個`Grid`布局用于展示生肖卡。通過`ForEach`方法,將每張生肖卡的數據綁定到`GridItem`中,并使用`Badge`組件在每張卡的右上角顯示其數量。此外,還添加了一個“立即抽卡”按鈕,用于觸發抽卡操作。
????????當點擊“立即抽卡”按鈕時,會觸發一系列的動畫效果和邏輯處理。首先,設置遮罩層的透明度、層級和縮放比例,使抽卡頁面顯示出來。然后,通過`Math.random()`方法生成一個隨機數,表示抽中的生肖卡序號。接著,將抽中的生肖卡以放大的形式顯示在抽卡頁面上,并提供一個“開心收下”按鈕。
????????點擊“開心收下”按鈕后,將遮罩層的透明度和層級恢復到初始狀態,并將抽中的生肖卡數量加1。同時,檢查是否所有生肖卡的數量都大于0,如果是,則表示集齊了所有生肖卡,可以進入中獎頁面。在中獎頁面中,會隨機選擇一個獎品(華為、蘋果或小米手機),并顯示相應的圖片和“再來一次”按鈕。點擊“再來一次”按鈕后,將所有生肖卡的數量重置為0,重新開始抽獎過程。
????????在整個實驗過程中,通過合理使用`State`變量來控制頁面的狀態變化,以及利用`ForEach`和`Badge`組件實現了動態的數據綁定和顯示效果。同時,通過`Grid`布局實現了生肖卡的規則排列,使得頁面布局更加美觀和清晰。
源代碼:
// 1.定義接口
interface Images{url:stringcount:number
}// 需求1:遮罩層顯隱 透明度opacity 0-1 層級zInsex 1-99
// 需求2:圖片收縮 縮放scale 0-1
@Entry
@Component
struct Index {// 隨機的生肖卡序號@State randomNum:number=-1// 初始值為-1表示還沒有抽卡// 2.基于接口準備數據@State images: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}]// 透明度@State transparent:number=0 // 初始為0//層級@State Level:number=0 // 初始為0// 縮放@State zoomx:number=0@State zoomy:number=0// 控制中獎@State isGet:boolean=false// 獎池@State arr:string[]=['pg','hw','xm']@State price:string=''//默認沒有中獎build() {// 層疊布局Stack(){// 初始化頁面Column(){// Grid布局的基礎使用:規則的行列布局中非常常見Grid(){ForEach(this.images,(item:Images,index:number)=>{GridItem(){Badge({count:item.count,position:BadgePosition.RightTop,style:{fontSize:14,badgeSize:20,badgeColor:Color.Red}}){Image($r(item.url)).width(100).height(100)}}})}.columnsTemplate('1fr 1fr 1fr').rowsTemplate('1fr 1fr').width('100%').height(300).margin({top:100})Button('立即抽卡').width(200).backgroundColor('#de668d').margin({top:50}).onClick(()=>{this.Level=99this.transparent=1this.zoomx=1this.zoomy=1//計算隨機數this.randomNum = Math.floor(Math.random()*6)})}.zIndex(5) // 初始化層級為5.width('100%').height('100%')// 抽卡時的頁面Column({space:25}){Text('獲得生肖卡片').fontColor('#f5ebcf').fontSize(25).fontWeight(FontWeight.Bold)Image($r(`app.media.img_0${this.randomNum}`)).width(200)// 卡片的播放.scale({x:this.zoomx,y:this.zoomy}).animation({duration:500})Button('開心收下').width(200).height(50).backgroundColor(Color.Transparent)// 透明色.border({width:2,color:'#fff9e0'}).onClick(()=>{this.transparent=0this.Level=0this.zoomx=0this.zoomy=0// 開心收下this.images[this.randomNum]={url:`app.media.img_0${this.randomNum}`,count:this.images[this.randomNum].count+1}// 判斷卡片的數量// 如果卡片中有一個的數量為0,那就是沒集齊let flag:boolean=truefor(let item of this.images){if(item.count==0){flag=falsebreak}}this.isGet=flagif(flag){let randomIndex:number=Math.floor(Math.random()*3)this.price=this.arr[randomIndex]}})}.justifyContent(FlexAlign.Center)// 居中對齊.width('100%').height('100%').backgroundColor('#cc000000').zIndex(this.Level).opacity(this.transparent)// 透明度// 動畫.animation({duration:200})if(this.isGet){// 中獎頁面Column(){Text('恭喜獲得手機一部').fontColor('#f5ebcf').fontSize(25).fontWeight(700)Image($r(`app.media.${this.price}`)).width(300)Button('再來一次').width(200).height(50).backgroundColor(Color.Transparent).border({width:2,color:'#fff9e0'}).onClick(()=>{this.isGet=falsethis.price=''this.images=[j{url:'app.media.img_00',count:0},{url:'app.media.img_01',count:0},{url:'app.media.img_02',count:0},{url:'app.media.img_03',count:0},{url:'app.media.img_04',count:0},{url:'app.media.img_05',count:0}]})}.zIndex(10).width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor('#cc000000')}}}
}
?運行截圖: