Taro Reacti native 實現九宮格抽
先上效果圖
說明
因爲這是中間按鈕點擊抽獎,所以實際獎品只有8個。
詳細註釋都在代碼中寫了註釋
state = {
//這是獎品,只有8個,圖是我在網上找的
LotteryData:
[
{
url:"https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/zhuanpanchoujiang/APP1031JFZP-score_10.png",
name: "10積分",
indexKey : 0
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/zhuanpanchoujiang/APP1031JFZP-666.png",
name: "666元現金",
indexKey : 1
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/renrenzuan/lottery/money_88.png",
name: "88元現金",
indexKey : 2
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/zhuanpanchoujiang/APP1031JFZP-money_10.png",
name: "10元優惠券",
indexKey : 3
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/zhuanpanchoujiang/APP1031JFZP-thanks.png",
name: "謝謝參與",
indexKey : 4
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/zhuanpanchoujiang/APP1031JFZP-score_100.png",
name: "100積分",
indexKey : 5
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/renrenzuan/lottery/money_168.png",
name: "168優惠券",
indexKey : 6
},
{
url: "https://m.renrendai.com/cms/59bb80994eac411e88fe8a9b/app/zhuanpanchoujiang/APP1031JFZP-score_50.png",
name: "50積分",
indexKey : 7
},
],
// 被選中的格子的ID
activedId: '',
// 中獎ID
prizeId: null,
// 獲得prizeId之後計算出的動畫次數
times: 0,
// 當前動畫次數
actTimes: 0,
// 是否正在抽獎
isRolling: false
handleBegin() {
// this.state.isRolling爲false的時候才能開始抽,不然會重複,報錯。
if (!this.state.isRolling) {
// 點擊抽獎之後,可以將於九宮格有關的狀態都還原默認。然後
this.setState({
activedId: '',
prizeId: null,
times: 0,
actTimes: 0,
isRolling: true
}, () => {
// 狀態還原再開始真正的抽獎
this.handlePlay()
})
}
}
handlePlay() {
//此處可以調用後臺。一般抽獎都是後臺返回前端
// 中將indexKey ,可隨機,可自己設定,我這裏暫且定爲5
let prize = 5
this.setState({
prizeId: prize,
activedId: 0
})
// 隨機算出一個動畫執行的最小次數,這裏可以隨機變更數值,按自己的需求來
let times = 20
this.setState({
times: times
})
// 抽獎正式開始
this.begin = setInterval(() => {
let num;
if (this.state.activedId === this.state.prizeId && this.state.actTimes > this.state.times) {
// 符合上述所有條件時纔是中獎的時候,兩個ID相同並且動畫執行的次數大於(或等於也行)設定的最小次數
clearInterval(this.begin)
//將抽獎狀態轉爲false。
this.setState({
isRolling: false
})
//這裏可以加一些modol等一些東西。轉盤結束,告訴用戶此次抽獎中否
return
}
// 以下是動畫執行時對id的判斷,每40秒執行一次
if (this.state.activedId === '') {
//從0開始轉動
num = 0
this.setState({
activedId: num
})
} else {
num = this.state.activedId
//從0開始轉動,轉到到7的時候,也就意味是最後一個,將num置爲0.重新開始轉
if (num === 7) {
num = 0
this.setState({
activedId: num
})
} else {
num = num + 1
this.setState({
activedId: num
})
}
}
this.setState({
actTimes: this.state.actTimes + 1
})
}, 40)
}
render() {
const { LotteryData,activedId } = this.state;
return (
{LotteryData&&LotteryData.length> 0 &&
<View className='lottery_box'>
<View className='lottery_box_s'>
// 當選中的id和indexKey相等時給加上active
<View className={activedId === LotteryData[0].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[0].indexKey}`} >
<Image className='lottery_box_view_img' src={LotteryData[0].prizeImageUrl} />
</View>
<View className={activedId === LotteryData[1].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[1].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[1].prizeImageUrl} />
</View>
<View className={activedId === LotteryData[2].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[2].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[2].prizeImageUrl} />
</View>
</View>
<View className='lottery_box_s'>
<View className={activedId === LotteryData[7].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[7].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[7].prizeImageUrl} />
</View>
<View className='lottery_box_view' onClick={this.handleBegin.bind()}>
<Image className='lottery_box_view_img' src={choujiang} />
</View>
<View className={activedId === LotteryData[3].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[3].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[3].prizeImageUrl} />
</View>
</View>
<View className='lottery_box_s'>
<View className={activedId === LotteryData[6].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[6].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[6].prizeImageUrl} />
</View>
<View className={activedId === LotteryData[5].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[5].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[5].prizeImageUrl} />
</View>
<View className={activedId === LotteryData[4].indexKey ? 'lottery_box_view lottery_box_view_active' : 'lottery_box_view'} id={`lottery_box_view_${LotteryData[4].indexKey}`}>
<Image className='lottery_box_view_img' src={LotteryData[4].prizeImageUrl} />
</View>
</View>
</View>
}
)
}
我的CSS如下,css也可以自己隨意發揮。
.lottery_box{
margin-top: 20px;
padding: 20px;
border-color: #fff;
border-style: solid;
border-width: 2px;
border-radius: 16px;
}
.lottery_box_view{
width: 33.3%;
padding: 4px;
border-radius:16px ;
}
.lottery_box_view_img{
width: 100%;
height: 160px;
border-radius:16px ;
}
.lottery_box_view_active{
background-color: black;
opacity: .8;
}
.lotterys{
background: #fff001;
width: 100%;
height: 420px;
min-height: 420px;
border-bottom-left-radius: 80px;
border-bottom-right-radius: 80px;
}
這只是簡易的效果。如果有興趣的話可以
可以研究一下轉盤運動剛開始加速,慢慢勻速,到最後減速並且停止的過程。
或者可以去看react-native-supper-lottery開源組件完成了佈局和動畫等核心功能,之後的封裝組件提供start、stop等抽獎函數就很簡單了,這裏不再詳述,詳細代碼可以參考組件react-native-supper-lottery,也可以直接使用。