本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫
本文主要介紹如何使用原生javascript和Css3來實現一個在各大移動應用中經常出現的轉盤遊戲,由於改實現可以有不同方式,如果熟悉canvas的話也可以用canvas實現,本文採用js和css實現主要考慮到複雜度較小性能較好,所以如果有更好的方案,也可以隨時和我交流。
前言
本文技術路線採用和上篇文章教你用200行代碼寫一個愛豆拼拼樂H5小遊戲(附源碼)同樣的技術,即均使用本人自己寫的dom庫去簡化dom操作,具體需要掌握的知識點有:
css3 背景漸變,transform,transitionless循環的使用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;
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)
})