JavaScript實(shí)踐之使用Canvas開發(fā)一個(gè)可配置的大轉(zhuǎn)盤抽獎(jiǎng)功能
??一、引言
大轉(zhuǎn)盤抽獎(jiǎng)是一種常見的游戲方式,用戶可以通過點(diǎn)擊按鈕讓指針開始旋轉(zhuǎn),在經(jīng)過一段時(shí)間后指針會(huì)停下來,顯示用戶中獎(jiǎng)的獎(jiǎng)項(xiàng)。本文將用
Javascript和HTML實(shí)現(xiàn)一個(gè)簡(jiǎn)單的大轉(zhuǎn)盤抽獎(jiǎng)功能。詳細(xì)介紹實(shí)現(xiàn)思路和代碼。
??文末附完整代碼??
??二、開發(fā)思路
本文將使用JavaScript和HTML來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的大轉(zhuǎn)盤抽獎(jiǎng)功能。具體步驟如下:
- 創(chuàng)建HTML結(jié)構(gòu):使用HTML創(chuàng)建一個(gè)大轉(zhuǎn)盤容器,包括轉(zhuǎn)盤、指針和抽獎(jiǎng)按鈕。
- 使用CSS樣式:使用CSS樣式來美化大轉(zhuǎn)盤的外觀,包括顏色、字體等。
- 使用JavaScript編寫抽獎(jiǎng)邏輯:根據(jù)配置的獎(jiǎng)項(xiàng)和概率,計(jì)算中獎(jiǎng)結(jié)果,并設(shè)置指針的旋轉(zhuǎn)動(dòng)畫效果。
- 綁定點(diǎn)擊事件:為抽獎(jiǎng)按鈕綁定點(diǎn)擊事件,點(diǎn)擊按鈕后開始抽獎(jiǎng)邏輯。
- 彈出中獎(jiǎng)內(nèi)容:抽獎(jiǎng)結(jié)束后,使用alert彈窗顯示中獎(jiǎng)結(jié)果。
??三、代碼實(shí)現(xiàn)
??3.1 HTML結(jié)構(gòu)(index.html)
<div id="canvas"> <canvas id="wheel" width="600" height="600"></canvas></div> <button onclick="startSpin()">抽獎(jiǎng)</button>
??3.2 CSS樣式(style.css)
css樣式主要定義圓盤和按鈕的顯示效果,核心代碼如下:
#canvas {
position: relative;
}
.block {
width: 200px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
}??3.3 JavaScript代碼(script.css)
??3.3.1 配置中獎(jiǎng)概率
先定義一個(gè)配置數(shù)組,用于配置獎(jiǎng)項(xiàng)的名稱抽獎(jiǎng)背景色以及中獎(jiǎng)的概率,后面圓盤會(huì)根據(jù)這個(gè)顯示出對(duì)應(yīng)的效果。
const prizes = [
{ text: '獎(jiǎng)品1', color: '#f44336', probability: 0.2 },
{ text: '獎(jiǎng)品2', color: '#9c27b0', probability: 0.1 },
{ text: '獎(jiǎng)品3', color: '#3f51b5', probability: 0.15 },
{ text: '獎(jiǎng)品4', color: '#00bcd4', probability: 0.25 },
{ text: '獎(jiǎng)品5', color: '#4caf50', probability: 0.2 },
{ text: '獎(jiǎng)品6', color: '#000000', probability: 0.1 }
];
??3.3.2 開發(fā)圓盤效果
根據(jù)上面的配置,來開發(fā)出圓盤,主要用到Javascript進(jìn)行編碼。
function drawWheel() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
let startAngle = 0;
let endAngle = 0;
for (let i = 0; i < prizes.length; i++) {
startAngle = endAngle;
endAngle = startAngle + (Math.PI * 2 * prizes[i].probability);
ctx.beginPath();
ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);
ctx.lineTo(centerX, centerY);
ctx.fillStyle = prizes[i].color;
ctx.fill();
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate((startAngle + endAngle) / 2);
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.fillText(prizes[i].text, radius / 2, 0);
ctx.restore();
}
}
現(xiàn)在來預(yù)覽一下圓盤效果,是不是還挺好看的。接下來繼續(xù)開發(fā)指針及旋轉(zhuǎn)中獎(jiǎng)效果。

??3.3.3 開發(fā)指針樣式
首先來一段css樣式來安排一下指針效果:
#pointer {
position: absolute;
top: calc(50% - 5px);
left: calc(50% - 2.5px);
width: 5px;
height: 30%;
background-color: red;
transform-origin: bottom center;
transition: transform 5s ease-in-out;
left: 300px;
top: 120px;
}
把下面的div放到index.html里面去,顯示效果如下圖。
<div id="pointer"></div>

??3.3.4 開發(fā)點(diǎn)擊抽獎(jiǎng)事件
我們通過點(diǎn)擊按鈕來觸發(fā)抽獎(jiǎng)動(dòng)作。當(dāng)用戶點(diǎn)擊按鈕時(shí)。開始旋轉(zhuǎn)抽獎(jiǎng)指針,并且在5秒后停止并顯示中獎(jiǎng)內(nèi)容。主要js代碼如下。
function spinWheel() {
if (!spinning) {
angle = angle % (Math.PI * 2);
ctx.clearRect(centerX - 10, centerY - radius - 10, 20, radius + 20);
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(-5, -radius - 5);
ctx.lineTo(5, -radius - 5);
ctx.lineTo(0, -radius - 15);
ctx.closePath();
ctx.fillStyle = 'red';
ctx.fill();
ctx.restore();
angle += 0.1;
requestAnimationFrame(spinWheel);
}
}
// 開始抽獎(jiǎng)邏輯
function startSpin() {
if (!spinning) {
genRandom()
spinning = true;
spinWheel();
pointerRotate()
setTimeout(stopSpin, 5000);
}
}
// 指針開始旋轉(zhuǎn)
function pointerRotate() {
const pointer = document.getElementById('pointer');
const rotation = 360 * random + 720;
// 設(shè)置動(dòng)畫
pointer.style.transform = 'rotateZ(' + rotation + 'deg)';
pointer.style.pointerEvents = 'none';
// 停止旋轉(zhuǎn)并彈出中獎(jiǎng)內(nèi)容
setTimeout(() => {
pointer.style.pointerEvents = 'auto';
}, 5000);
}
// 指針停止事件
function stopSpin() {
spinning = false;
const selectedPrize = getSelectedPrize();
alert('中獎(jiǎng)內(nèi)容:' + selectedPrize.text);
}
// 根據(jù)旋轉(zhuǎn)角度獲取中獎(jiǎng)內(nèi)容
function getSelectedPrize() {
let startAngle = 0;
let endAngle = prizes[0].probability;
for (let i = 0; i < prizes.length; i++) {
if (random >= startAngle && random < endAngle) {
return prizes[i];
}
startAngle = endAngle;
endAngle += prizes[i + 1].probability;
}
}
??四、測(cè)試效果
在實(shí)際場(chǎng)景中假設(shè)我們?cè)O(shè)計(jì)如下5個(gè)獎(jiǎng)項(xiàng)。點(diǎn)擊抽獎(jiǎng)按鈕,可以看到指針轉(zhuǎn)動(dòng),5秒后停止并彈出中獎(jiǎng)內(nèi)容。
macbook 14pro,中獎(jiǎng)概率10%。iPhone13,中獎(jiǎng)概率30%。xiaomi手機(jī),中獎(jiǎng)概率20%。100元商城優(yōu)惠券,中獎(jiǎng)概率20%。感謝參與,中獎(jiǎng)概率20%。
const prizes = [
{ text: 'macbook14pro', color: '#f44336', probability: 0.1 },
{ text: 'iPhone13', color: '#9c27b0', probability: 0.3 },
{ text: 'xiaomi', color: '#3f51b5', probability: 0.2 },
{ text: '100元優(yōu)惠券', color: '#00bcd4', probability: 0.2 },
{ text: '感謝參與', color: '#4caf50', probability: 0.2 },
];

??五、完整代碼
??5.1 index.html
<!DOCTYPE html>
<html>
<head>
<title>大轉(zhuǎn)盤抽獎(jiǎng)</title>
<link rel="stylesheet" type="text/css" href="style.css" rel="external nofollow" >
</head>
<body>
<div id="canvas">
<canvas id="wheel" width="600" height="600"></canvas>
<div id="pointer"></div>
</div>
<button onclick="startSpin()">抽獎(jiǎng)</button>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
??5.2 style.css
#canvas {
position: relative;
width: 600px;
height: 600px;
}
#pointer {
position: absolute;
top: calc(50% - 5px);
left: calc(50% - 2.5px);
width: 5px;
height: 30%;
background-color: red;
transform-origin: bottom center;
transition: transform 5s ease-in-out;
left: 300px;
top: 120px;
}
.block {
width: 200px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
}
??5.3 script.js
const prizes = [
{ text: 'macbook14pro', color: '#f44336', probability: 0.1 },
{ text: 'iPhone13', color: '#9c27b0', probability: 0.3 },
{ text: 'xiaomi', color: '#3f51b5', probability: 0.2 },
{ text: '100元優(yōu)惠券', color: '#00bcd4', probability: 0.2 },
{ text: '感謝參與', color: '#4caf50', probability: 0.2 },
];
const canvas = document.getElementById('wheel');
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = Math.min(canvas.width, canvas.height) / 2;
let angle = 0;
let spinning = false;
function drawWheel() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
let startAngle = 0;
let endAngle = 0;
for (let i = 0; i < prizes.length; i++) {
startAngle = endAngle;
endAngle = startAngle + (Math.PI * 2 * prizes[i].probability);
ctx.beginPath();
ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);
ctx.lineTo(centerX, centerY);
ctx.fillStyle = prizes[i].color;
ctx.fill();
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate((startAngle + endAngle) / 2);
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.fillText(prizes[i].text, radius / 2, 0);
ctx.restore();
}
}
function spinWheel() {
if (!spinning) {
angle = angle % (Math.PI * 2);
ctx.clearRect(centerX - 10, centerY - radius - 10, 20, radius + 20);
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(-5, -radius - 5);
ctx.lineTo(5, -radius - 5);
ctx.lineTo(0, -radius - 15);
ctx.closePath();
ctx.fillStyle = 'red';
ctx.fill();
ctx.restore();
angle += 0.1;
requestAnimationFrame(spinWheel);
}
}
function startSpin() {
if (!spinning) {
genRandom()
spinning = true;
spinWheel();
pointerRotate()
setTimeout(stopSpin, 5000);
}
}
function pointerRotate() {
const pointer = document.getElementById('pointer');
const rotation = 360 * random + 720;
// 設(shè)置動(dòng)畫
pointer.style.transform = 'rotateZ(' + rotation + 'deg)';
pointer.style.pointerEvents = 'none';
// 停止旋轉(zhuǎn)并彈出中獎(jiǎng)內(nèi)容
setTimeout(() => {
pointer.style.pointerEvents = 'auto';
}, 5000);
}
function stopSpin() {
spinning = false;
const selectedPrize = getSelectedPrize();
alert('中獎(jiǎng)內(nèi)容:' + selectedPrize.text);
}
function getSelectedPrize() {
let startAngle = 0;
let endAngle = prizes[0].probability;
for (let i = 0; i < prizes.length; i++) {
if (random >= startAngle && random < endAngle) {
return prizes[i];
}
startAngle = endAngle;
endAngle += prizes[i + 1].probability;
}
}
var random = Math.random()
function genRandom() {
random = Math.random()
}
drawWheel();
??六、總結(jié)
本文使用JavaScript和HTML實(shí)現(xiàn)了一個(gè)的大轉(zhuǎn)盤抽獎(jiǎng)功能。通過配置獎(jiǎng)項(xiàng)和概率,用戶可以根據(jù)自己的需要來設(shè)置抽獎(jiǎng)的規(guī)則。點(diǎn)擊抽獎(jiǎng)按鈕后,指針開始旋轉(zhuǎn),經(jīng)過5秒后停止,并彈出中獎(jiǎng)內(nèi)容。
以上就是本文的具體思路和代碼實(shí)現(xiàn),通過這個(gè)示例,你可以了解到如何使用JavaScript和HTML來實(shí)現(xiàn)大轉(zhuǎn)盤抽獎(jiǎng)功能。希望對(duì)你有所幫助!實(shí)際的應(yīng)用中,可以基于上面的內(nèi)容修改。
到此這篇關(guān)于JavaScript使用Canvas開發(fā)一個(gè)可配置的大轉(zhuǎn)盤抽獎(jiǎng)功能的文章就介紹到這了,更多相關(guān)JS Canvas大轉(zhuǎn)盤抽獎(jiǎng)功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)在頁面刷新時(shí)成功發(fā)送停止請(qǐng)求
最近接到一個(gè)需求,需要在頁面刷新或者關(guān)閉瀏覽器標(biāo)簽頁的時(shí)候觸發(fā)停止當(dāng)前sql的接口,所以本文小編給大家詳細(xì)介紹了解決方案和實(shí)現(xiàn)代碼,需要的朋友可以參考下2023-11-11
微信小程序wx.getImageInfo()如何獲取圖片信息
這篇文章主要為大家詳細(xì)介紹了微信小程序wx.getImageInfo()如何獲取圖片信息,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
uniapp打開地圖直接獲取位置的實(shí)現(xiàn)代碼
這篇文章主要介紹了uniapp打開地圖直接獲取位置的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-08-08
javascript對(duì)數(shù)組的常用操作代碼 數(shù)組方法總匯
js下數(shù)組也是比較常用的,對(duì)數(shù)組元素的處理也是有非常多的方法,這里整理了下,需要的朋友可以參考下。2011-01-01
firefox TBODY 用js顯示和隱藏時(shí)出現(xiàn)錯(cuò)位的解決方法
今天幫別人寫一個(gè)網(wǎng)頁,發(fā)現(xiàn):當(dāng)用javascript動(dòng)態(tài)設(shè)置tr.style.display = "block"顯示某行時(shí),使用IE瀏覽沒有問題,但使用firefox瀏覽時(shí)該行被移到了其它行的后面,很是詫異。2008-12-12
javascript函數(shù)中參數(shù)傳遞問題示例探討
本節(jié)主要與大家探討下javascript函數(shù)中參數(shù)傳遞問題,有不明白的朋友可以參考下2014-07-07
原生JS實(shí)現(xiàn)點(diǎn)擊數(shù)字小游戲
這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)點(diǎn)擊數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04

