本人主要介紹如何在微信小程序里面開發(fā)一個(gè)幸運(yùn)轉(zhuǎn)盤的小游戲,里面主要用到j(luò)avascript和 css 語法,就可以輕松實(shí)現(xiàn)一個(gè)簡單的幸運(yùn)轉(zhuǎn)盤(以6個(gè)獎(jiǎng)品區(qū)為例)。
前言
本次教程需要你掌握一定量 javascript 和 css 基礎(chǔ)知識(shí),并且你需要有小程序一定的開發(fā)經(jīng)驗(yàn),具體需要掌握知識(shí)點(diǎn)有:
- css 的 position、transform、transition、overflow
- javascript基本隨機(jī)算法
- wxs語法
- 小程序內(nèi)置動(dòng)畫api
效果圖
小程序開發(fā)思路
開發(fā)思路有三部分,第一部分是用css繪制轉(zhuǎn)盤背景,第二部分是利用 wxs 語法實(shí)現(xiàn)響應(yīng)式樣式 ,第三部分是小程序內(nèi)置動(dòng)畫api實(shí)現(xiàn)轉(zhuǎn)盤的轉(zhuǎn)動(dòng)以及通過js轉(zhuǎn)動(dòng)隨機(jī)性的實(shí)現(xiàn)。
本人主要介紹編寫思路,下面就開始我的講解。
如何畫一個(gè)三角形
一開始,要寫一個(gè)基礎(chǔ)的 wxml 框架。
1
2
3
4
5
6
7
8
9
|
< view class = "turntable" > < view class = "wrapper" > < view class = "item" > < view class = "item-inner" > < text >10分</ text > </ view > </ view > </ view > </ view > |
我畫了兩個(gè)大小相同的長方形,長和寬分別是300rpx和600rpx,利用 position css屬性,讓兩個(gè)長方形合并在一起。
1
2
3
4
5
6
7
8
9
10
11
|
.turntable { display : block ; width : 100% ; height : 600 rpx; } .turntable .wrapper{ position : relative ; transform-origin: center ; width : 100% ; height : 600 rpx; } |
合并之后我需要將兩個(gè)長方體分離出來,把紅色長方體變成半圓形,藍(lán)色長方體順時(shí)擺動(dòng)60度,紅色長方體逆時(shí)擺動(dòng)30度,為什么要這樣轉(zhuǎn),因?yàn)樗{(lán)色本來隨紅色逆時(shí)擺動(dòng)30度,而一個(gè)三角形內(nèi)角為60度,為了形成這60度的夾角,我需要紅色擺完之后再將藍(lán)色順時(shí)移動(dòng)60度,也就這樣形成60度夾角。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
.turntable .wrapper .item { position : absolute ; left : 50% ; width : 300 rpx; height : 600 rpx; border-radius: 0px 300 rpx 300 rpx 0 ; transform-origin: left center ; transform: rotate( -30 deg); } .turntable .wrapper .item .item-inner { text-align : center ; width : 300 rpx; height : 600 rpx; transform: translateX( -300 rpx) rotate( 60 deg); transform-origin: right center ; border-radius: 300 rpx 0 0 300 rpx; font-size : 32 rpx; } |
接下來關(guān)鍵一步在 item 處增加 overflow: hidden 屬性,一個(gè)三角形就出來了,并調(diào)整字體的位置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
.turntable .wrapper .item { position : absolute ; left : 50% ; width : 300 rpx; height : 600 rpx; border-radius: 0px 300 rpx 300 rpx 0 ; overflow : hidden ; transform-origin: left center ; } .turntable .wrapper .item .item-inner text { display : block ; transform-origin: center ; transform: translateY( 100 rpx) translateX( 43 rpx) rotate( -30 deg); } |
一個(gè)三角形畫出來后,將6個(gè)同等大小的三角形并讓他們可以拼接在一起組合成一個(gè)圓盤,只需各自修改三角的旋轉(zhuǎn)角度即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
.turntable .wrapper .item:nth-child( 1 ) { transform: rotate( -30 deg); } .turntable .wrapper .item:nth-child( 2 ) { transform: rotate( -90 deg); } .turntable .wrapper .item:nth-child( 3 ) { transform: rotate( -150 deg); } .turntable .wrapper .item:nth-child( 4 ) { transform: rotate( -210 deg); } .turntable .wrapper .item:nth-child( 5 ) { transform: rotate( -270 deg); } .turntable .wrapper .item:nth-child( 6 ) { transform: rotate( -330 deg); } |
實(shí)現(xiàn)響應(yīng)式樣式
為了更好的適應(yīng)不同業(yè)務(wù)需求,我把轉(zhuǎn)盤的樣式變成響應(yīng)式,就可以輕松根據(jù)用外部傳入的 prize 數(shù)據(jù)的長度來設(shè)置不同的樣式,我把這一步的判斷,放在 wxs 模塊那里。
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
|
< wxs module = "computed" > var rotate = function (index, length) { var inital = - (360 / length / 2) var averageRotate = 360 / length var deg = inital - averageRotate * index return 'transform: rotate(' + deg + 'deg);' } var inner = function (length) { var averageRotate = 360 / length return 'transform: translateX(-300rpx) rotate(' + averageRotate + 'deg);' } var text = function (length) { var distance = 0 var rotate = 0 switch (length) { case 6: distance = 43 rotate = 30 break case 8: distance = 72 rotate = 30 break case 4: distance = -20 rotate = 40 break } return 'transform: translateY(100rpx) translateX(' + distance + 'rpx) rotate(-45deg);' } module.exports = { rotate: rotate, inner: inner, text: text } </ wxs > |
動(dòng)畫系統(tǒng)和中獎(jiǎng)系統(tǒng)
通過設(shè)定好的中獎(jiǎng)率,以一個(gè)圓為360度來計(jì)算,得出一個(gè)0-360的中獎(jiǎng)范圍,將隨機(jī)得來的數(shù)判斷屬于哪個(gè)區(qū)間值,用區(qū)間值 reward 來決定圓盤所需轉(zhuǎn)動(dòng)的角度。思路大概就是這樣,下面開始講解主要的思路。
圓盤要轉(zhuǎn)的角度 = reward * 一個(gè)圓分成6塊的平均值 + 3 * 360
首先要設(shè)置好6個(gè)獎(jiǎng)品區(qū)的中獎(jiǎng)率winning,該中獎(jiǎng)率要相加起來為1,把初始化的數(shù)據(jù)組合成一個(gè)6位數(shù)的數(shù)組從組件外傳入進(jìn)組件內(nèi)。
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
|
prize: [{ 'name' : '1分' , 'winnning' : 0.2 , 'count' : 1 }, { 'name' : '謝謝參與' , 'winnning' : 0.5 , 'count' : 0 }, { 'name' : '5分' , 'winnning' : 0.05 , 'count' : 5 }, { 'name' : '7分' , 'winnning' : 0.05 , 'count' : 7 }, { 'name' : '3分' , 'winnning' : 0.1 , 'count' : 3 }, { 'name' : '4分' , 'winnning' : 0.1 , 'count' : 4 } ], |
以一個(gè)圓為360度來計(jì)算出0-360的中獎(jiǎng)取值范圍。
1
2
3
4
5
6
7
8
9
10
11
|
getRange(winning) { let temp = [] winning.forEach((item, index) => { if (index === 0) { temp.push(item[ 'winnning' ] * 360) } else { temp.push(parseInt(temp.slice(-1)) + item[ 'winnning' ] * 360) } }) return temp }, |
生成一個(gè)隨機(jī)整數(shù),當(dāng)然這數(shù)要在0-360,不然超出360或小于0是沒有意義的。
1
|
let random = Math.round(Math.random() * 360) |
獲得隨機(jī)數(shù)之后,判斷在哪個(gè)獎(jiǎng)品范圍內(nèi)并把在對(duì)應(yīng)的區(qū)間值賦予響應(yīng)數(shù)reward 內(nèi)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
for (let i in winningRange) { let currentwinning = winningRange[i] // 當(dāng)前取值 if (random < currentwinning) { this .setData({ reward: i }) break } else { if (i == 0) { continue } if (random >= winningRange[i - 1] && random <= currentwinning) { this .setData({ reward: i }) break } } } |
把點(diǎn)擊開始的主函數(shù)放在onPoint()內(nèi),函數(shù)開始時(shí)需判斷是否仍有抽獎(jiǎng)機(jī)會(huì)以及防止在執(zhí)行動(dòng)畫又點(diǎn)擊函數(shù)執(zhí)行動(dòng)畫,經(jīng)過計(jì)算得來所需的角度通過微信小程序的動(dòng)畫api animation 來讓圓盤實(shí)現(xiàn)轉(zhuǎn)動(dòng),動(dòng)畫結(jié)束后把中獎(jiǎng)信息通過自定義組件觸發(fā)事件來讓組件外監(jiān)聽到。
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
|
onPoint() { // 平均值 const averageRotate = 360 / this .properties.prize.length // 是否有抽獎(jiǎng)機(jī)會(huì) if ( this .properties.chance === 0) { this .triggerEvent( 'none' ) return } // 防止轉(zhuǎn)動(dòng)時(shí)點(diǎn)擊開始按鈕 if (! this .data.onRotation) { this .setData({ onRotation: true }) this .getReward() let deg = this .data.reward * averageRotate + 3 * 360 // 至少3圈以上 this .animate( '.wrapper' , [{ rotate: 0, ease: 'ease-in-out' }, { rotate: deg, ease: 'ease-in-out' } ], 5000, function () { this .setData({ onRotation: false }) // 發(fā)送自己的抽獎(jiǎng)信息 this .triggerEvent( 'onResult' , this .properties.prize[ this .data.reward]) }.bind( this )) } }, |
最后別忘了在每次執(zhí)行動(dòng)畫前,都要先執(zhí)行動(dòng)畫重置動(dòng)作,才能保證動(dòng)畫下次轉(zhuǎn)到正確的角度。當(dāng)然我把其放在一個(gè)函數(shù)里面,以便組件外也可以使用該函數(shù)。
1
2
3
|
onClear(){ this .clearAnimation( '.wrapper' ) } |
最后
整個(gè)思路就這些,怎么樣,是不是很簡單呢?實(shí)現(xiàn)關(guān)鍵一步是繪制圓盤,只要這一步搞好了,其他就會(huì)簡單很多,因?yàn)閯?dòng)畫實(shí)現(xiàn)那部分,微信小程序已經(jīng)幫我們?nèi)颗昧恕W詈螅绻懈玫姆椒ǎ瑲g迎在評(píng)論討論一下。
特別要說一下,該轉(zhuǎn)盤項(xiàng)目放在我微信小程序?qū)嵗羞\(yùn)行,大家可以掃碼進(jìn)去小程序,在主頁最下面就能看到入口端口。
轉(zhuǎn)盤代碼倉: turntable
到此這篇關(guān)于如何在微信小程序?qū)崿F(xiàn)一個(gè)幸運(yùn)轉(zhuǎn)盤小游戲的文章就介紹到這了,更多相關(guān)小程序幸運(yùn)轉(zhuǎn)盤小游戲內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://juejin.cn/post/6893705980085796872