本文主要介紹如何使用原生javascript和Css3來實作一個在各大移動應用中經常出現的轉盤遊戲,由于改實作可以有不同方式,如果熟悉canvas的話也可以用canvas實作,本文采用js和css實作主要考慮到複雜度較小性能較好,是以如果有更好的方案,也可以随時和我交流。
前言
本文技術路線采用和上篇文章教你用200行代碼寫一個愛豆拼拼樂H5小遊戲(附源碼)同樣的技術,即均使用本人自己寫的dom庫去簡化dom操作,具體需要掌握的知識點有:
- css3 背景漸變,transform,transition
- less循環的使用
- javascript基本随機算法
- 文檔片段 documentFragment的使用
由于文章沒有太高深的技術,關鍵是思路,是以接下來開始我們的實作介紹。
效果圖
實作思路
實作思路分兩部分,第一部分是用css繪制轉盤背景,第二部分是通過js實作轉盤的轉動以及轉動随機性的實作。
1. 繪制轉盤背景
我們采用背景漸變的方式去實作條紋交替的扇形,原理就是通過繪制一個半圓,并在半圓裡加漸變來實作,如下圖:
實作将方形變成半圓的css我們通過border-radius來實作:
width: 150px;
height: 300px;
border-radius: 0 150px 150px 0;
我們再通過css的線性漸變,這樣本基本上可以實作一個小的扇形區域:
漸變的代碼如下:
background-image: linear-gradient(120deg, #f6d365, #f6d365 75px, transparent 75px);
實作了一個扇形,我們自然可以通過計算,比如我們扇形弧度為30deg,那麼我們需要12個扇形即可組成一個圓,為了友善,我們使用less的循環來實作:
.loop(@n) when (@n >= 0) {
.loop(@n - 1);
[email protected]{n} {
transform: rotate(-30deg * (@n + 1));
}
}
還有一個細節是,我們需要改變變換的中心點,讓每個扇形都以一個中心點渲染,這樣才可以組成一個完整的圓:
完整的css大緻如下:
2.javascript實作轉盤邏輯
由于轉盤的轉動是随機的,是以我們需要每次點選開始按鈕都要随機生成一個角度,但是仔細分析一些平台會發現轉盤每次都至少轉動n圈後才會慢慢開始停下,是以我們會給轉盤一個初始的角度,比如720deg,1080deg,這樣能保證轉盤至少轉動n圈才停下來。
另一個注意點是我們要如何通過轉動角度知道轉盤停下來後的位置?這裡處于性能問題,我們盡量不操作dom,通過資料控制,我們可以通過每次随機後得到的角度和機關扇形區域的弧度來計算停下來的位置,公式如下:
totalRadis = initRadis + radis * n + radis/2
totalRadis為轉動的角度,initRadis為初始化角度,radis為扇形的角度,radis/2是中獎的範圍,這裡主要用來定位用的,n是随機數,接下來我将解釋n的作用。
那麼怎麼實作随機角度呢?我們一般會想通過寫個随機函數去做,不過這裡有一種新的思路,就是通過随機生成中獎的位置來實作随機角度,由于我的扇形為30度,一共有12個扇形獎品區,是以索引為0-11。是以,上面講到的n,就是我們的随機索引,我們隻需要寫個生成指定範圍的随機數就可以了。
了解了以上知識,我們開始準備初始化資料:
渲染獎品資料,這裡我們用了DocumentFragment,雖然對簡單渲染沒有必要,但是後期可能會很有用:
生成指定範圍的随機數的方法:
// 生成從 start到end的随機數
function randomArr(start, end) {
return Math.round(start + Math.random()* (end - start))
}
當我們點選開始按鈕時,我将通過改變轉盤的transform來讓其運動起來:
// 轉動邏輯
var radis = 30, // 每個扇形區域的度數
n = randomArr(0, 360/radis), // 計算随機中獎的位置
initRadis = 720, // 初始轉動的角度
time = 16 * 1000, // 轉動時間
once = true, // 限制一個轉動周期隻能點選一次
totalRadis = initRadis + radis * n + radis/2; // 轉動角度計算公式
$('.start').on('click', function(){
if(once) {
once = false;
$('#piece_wrap').css({
'transform':'rotate(' + totalRadis + 'deg)',
'transition': 'transform 16s cubic-bezier(0,.47,.31,1.03)'
});
setTimeout(function(){
once = true;
alert('恭喜你抽中了' + wards[n] + '!');
$('#piece_wrap').css({
'transform':'rotate(' + 0 + 'deg)',
'transition': 'none'
});
}, time)
}
})
核心代碼就這些,怎麼樣,是不是很簡單呢?如果想體驗實際案例效果和技術交流,或者感受更多原創h5遊戲demo,可以關注下方公衆号體驗哦
更多推薦
- 教你用200行代碼寫一個愛豆拼拼樂H5小遊戲(附源碼)
- 基于react/vue生态的前端內建解決方案探索與總結
- 9012教你如何使用gulp4開發項目腳手架
- 如何用不到200行代碼寫一款屬于自己的js類庫)
- 讓你瞬間提高工作效率的常用js函數彙總(持續更新)
- 一張圖教你快速玩轉vue-cli3
- 3分鐘教你用原生js實作具有進度監聽的檔案上傳預覽元件
- 使用Angular8和百度地圖api開發《旅遊清單》
- js基本搜尋算法實作與170萬條資料下的性能測試
- 《前端算法系列》如何讓前端代碼速度提高60倍
- vue進階進階系列——用typescript玩轉vue和vuex
歡迎關注下方公衆号,擷取更多前端知識精粹和學習社群:
在公衆号點選進群,可以加入vue學習小組,一起學習前端技術;
回複 學習路徑,将擷取筆者多年從業經驗的前端學習路徑的思維導圖
趣談前端
Vue、React、小程式、Node
前端 算法|性能|架構|安全