JavaScript實(shí)踐之使用Canvas開發(fā)一個(gè)可配置的大轉(zhuǎn)盤抽獎(jiǎng)功能
??一、引言
大轉(zhuǎn)盤抽獎(jiǎng)是一種常見的游戲方式,用戶可以通過點(diǎn)擊按鈕讓指針開始旋轉(zhuǎn),在經(jīng)過一段時(shí)間后指針會停下來,顯示用戶中獎(jiǎng)的獎(jiǎng)項(xiàng)。本文將用
Javascript
和HTML實(shí)現(xiàn)一個(gè)簡單的大轉(zhuǎn)盤抽獎(jiǎng)功能。詳細(xì)介紹實(shí)現(xiàn)思路和代碼。
??文末附完整代碼??
??二、開發(fā)思路
本文將使用JavaScript
和HTML
來實(shí)現(xiàn)一個(gè)簡單的大轉(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)的概率,后面圓盤會根據(jù)這個(gè)顯示出對應(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; } }
??四、測試效果
在實(shí)際場景中假設(shè)我們設(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)功能。希望對你有所幫助!實(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)在頁面刷新時(shí)成功發(fā)送停止請求
最近接到一個(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-01uniapp打開地圖直接獲取位置的實(shí)現(xiàn)代碼
這篇文章主要介紹了uniapp打開地圖直接獲取位置的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-08-08javascript對數(shù)組的常用操作代碼 數(shù)組方法總匯
js下數(shù)組也是比較常用的,對數(shù)組元素的處理也是有非常多的方法,這里整理了下,需要的朋友可以參考下。2011-01-01firefox 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-12javascript函數(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