本文主要介紹如何使用原生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);
.piece-@{n} {
transform: rotate(-30deg * (@n + 1));
}
}
複製程式碼
還有一個細節是,我們需要改變變換的中心點,讓每個扇形都以一箇中心點渲染,這樣才可以組成一個完整的圓:
transform-origin: left center;
複製程式碼
完整的css大致如下:
.piece-wrap {
position: relative;
width: 300px;
height: 300px;
margin: 100px auto auto 173px;
transform-origin: left center;
transition: transform 16s cubic-bezier(0,.47,.31,1.03);
.piece {
position: absolute;
left: 0;
top: 0;
width: 150px;
height: 300px;
border-radius: 0 150px 150px 0;
transform-origin: left center;
span {
margin-left: 16px;
margin-top: 20px;
display: inline-block;
color: #fff;
}
&:nth-child(2n) {
background-image: linear-gradient(120deg, #f6d365, #f6d365 75px, transparent 75px);
}
&:nth-child(2n+1) {
background-image: linear-gradient(120deg, #ff5858, #ff5858 75px, transparent 75px);
}
}
.loop(@n) when (@n >= 0) {
.loop(@n - 1);
.piece-@{n} {
transform: rotate(-30deg * (@n + 1));
}
}
.loop(11);
}
複製程式碼
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,就是我們的隨機索引,我們只需要寫個生成指定範圍的隨機數就可以了。
瞭解了以上知識,我們開始準備初始化資料:
// 轉盤抽獎資料
var wards = ['1元', '2元', '3元', '5元', '再來',
'演算法', '0.5元', '0.1元', '0.2元', '0.6元',
'0.5元', '來'];
複製程式碼
渲染獎品資料,這裡我們用了DocumentFragment,雖然對簡單渲染沒有必要,但是後期可能會很有用:
// 渲染dom
var fragment = document.createDocumentFragment();
for(var i=0, len = wards.length; i < len; i++) {
var piece = document.createElement('div');
piece.className = 'piece piece-' + i;
piece.innerHTML = '<span>' + wards[i] + '</span>';
fragment.appendChild(piece);
}
$('#piece_wrap')[0].appendChild(fragment);
複製程式碼
生成指定範圍的隨機數的方法:
// 生成從 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實現具有進度監聽的檔案上傳預覽元件
- 3分鐘教你用原生js實現具有進度監聽的檔案上傳預覽元件
- 使用Angular8和百度地圖api開發《旅遊清單》
- js基本搜尋演算法實現與170萬條資料下的效能測試
- 《前端演算法系列》如何讓前端程式碼速度提高60倍
- 《前端演算法系列》陣列去重
- vue高階進階系列——用typescript玩轉vue和vuex
- 前端三年,談談最值得讀的5本書籍