Last active
October 23, 2024 09:22
-
-
Save housamz/256fcaae7211cce040352e8f8dd6a9ff to your computer and use it in GitHub Desktop.
Raffle Draw Lucky wheel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.controls-container | |
h3#headline Insert Names Here | |
small#subheader (separated by commas or new lines) | |
span#counter | |
textarea#names(rows="10", cols="40"). | |
Ben, David, Declan, Housam, Jeongtae, Kevin, Ming, Robin | |
small#counter | |
button#spin Spin The Wheel | |
button#remove Remove Winner | |
.container | |
#wheel |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let names = [], | |
colors = [], | |
sliceDeg, | |
speed = 0, | |
slowDownRand = 0, | |
ctx, | |
width, | |
center, | |
deg, | |
isStopped = false, | |
lock = false, | |
winner, | |
namesContainer = document.getElementById("names"); | |
let shuffle = (array) => { | |
for (let i = array.length - 1; i > 0; i--) { | |
var j = Math.floor(Math.random() * (i + 1)); | |
var temp = array[i]; | |
array[i] = array[j]; | |
array[j] = temp; | |
} | |
}; | |
let checkTextArea = () => { | |
names = namesContainer.value | |
.replace(/\n/g, ",") // convert line breaks to commas | |
.replace(/,\s*$/, "") // remove last comma | |
.split(",") | |
.map(function (item) { | |
return item.trim(); | |
}); | |
document.getElementById("counter").innerText = names.length + " names"; | |
sliceDeg = 360 / names.length; | |
}; | |
let fillColors = () => { | |
let color; | |
while (colors.length < names.length) { | |
do { | |
color = Math.floor(Math.random() * 1000000 + 1); | |
} while (colors.indexOf(color) >= 0); | |
colors.push("#" + ("000000" + color.toString(16)).slice(-6)); | |
} | |
}; | |
let rand = (min, max) => { | |
return Math.random() * (max - min) + min; | |
}; | |
deg = rand(0, 360); | |
let deg2rad = (deg) => { | |
return (deg * Math.PI) / 180; | |
}; | |
let drawSlice = (deg, color) => { | |
ctx.beginPath(); | |
ctx.fillStyle = color; | |
ctx.moveTo(center, center); | |
ctx.arc(center, center, width / 2, deg2rad(deg), deg2rad(deg + sliceDeg)); | |
ctx.lineTo(center, center); | |
ctx.fill(); | |
}; | |
let drawText = (deg, text) => { | |
ctx.save(); | |
ctx.translate(center, center); | |
ctx.rotate(deg2rad(deg)); | |
ctx.textAlign = "right"; | |
ctx.fillStyle = "#fff"; | |
ctx.font = "bold 20px 'Open Sans', sans-serif"; | |
ctx.fillText(text, center - 20, center / (names.length * 2)); | |
ctx.restore(); | |
}; | |
let drawImg = () => { | |
width = | |
(names.length + 2) * 30 > 300 ? (names.length + 2) * 30 : 300; | |
canvas = document.createElement("canvas"); | |
document.getElementById("wheel").innerHTML = ""; | |
document.getElementById("wheel").appendChild(canvas); | |
ctx = canvas.getContext("2d"); | |
canvas.width = width; | |
canvas.height = width; | |
center = width / 2; | |
fillColors(); | |
ctx.clearRect(0, 0, width, width); | |
for (let i = 0; i < names.length; i++) { | |
drawSlice(deg, colors[i]); | |
drawText(deg + sliceDeg / 2, names[i]); | |
deg += sliceDeg; | |
} | |
}; | |
let anim = () => { | |
deg += speed; | |
deg %= 360; | |
// Increment speed | |
if (!isStopped && speed < 3) { | |
speed = speed + 1 * 0.1; | |
} | |
// Decrement Speed | |
if (isStopped) { | |
if (!lock) { | |
lock = true; | |
slowDownRand = rand(0.2, 0.9); | |
} | |
speed = speed > 0.2 ? (speed *= slowDownRand) : 0; | |
} | |
// Stopped! | |
if (lock && !speed) { | |
let ai = Math.floor(((360 - deg - 90) % 360) / sliceDeg); // deg 2 Array Index | |
ai = (names.length + ai) % names.length; // Fix negative index | |
winner = ai; | |
return alert("You got:\n" + names[ai]); // Get Array Item from end Degree | |
} | |
drawImg(); | |
window.requestAnimationFrame(anim); | |
}; | |
let reset = () => { | |
shuffle(names); | |
sliceDeg = 360 / names.length; | |
drawImg(); | |
}; | |
document.getElementById("spin").addEventListener( | |
"mousedown", | |
() => { | |
anim(); | |
setTimeout(function () { | |
isStopped = true; | |
}, 1900); | |
setTimeout(function () { | |
speed = 0; | |
slowDownRand = 0; | |
isStopped = false; | |
lock = false; | |
}, 3000); | |
}, | |
false | |
); | |
namesContainer.addEventListener( | |
"input", | |
() => { | |
checkTextArea(); | |
reset(); | |
}, | |
false | |
); | |
document.getElementById("remove").addEventListener( | |
"mousedown", | |
() => { | |
names.splice(winner, 1); | |
reset(); | |
}, | |
false | |
); | |
checkTextArea(); | |
drawImg(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap"); | |
body, | |
textarea, | |
button { | |
font-family: "Open Sans", sans-serif; | |
font-size: 18px; | |
} | |
body { | |
display: flex; | |
justify-content: center; | |
padding-top: 50px; | |
} | |
.controls-container { | |
position: fixed; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
z-index: 100; | |
background-color: white; | |
padding: 40px 40px 0 40px; | |
} | |
#headline { | |
margin: 0; | |
} | |
#subheader { | |
display: block; | |
margin-bottom: 10px; | |
} | |
textarea { | |
padding: 10px; | |
border: 1px solid #ccc; | |
border-radius: 5px; | |
display: block; | |
} | |
button { | |
font-weight: bold; | |
background-color: #027bc7; | |
border-color: transparent; | |
color: white; | |
border-radius: 5px; | |
margin: 10px 0; | |
padding: 10px 20px; | |
&:nth-of-type(2) { | |
background-color: #ca0d30; | |
float: right; | |
} | |
} | |
#wheel { | |
position: relative; | |
overflow: hidden; | |
margin: 0 0 0 60px; | |
&:after { | |
content: ""; | |
background: red; | |
border: 2px solid white; | |
position: absolute; | |
top: -7px; | |
left: 50%; | |
width: 10px; | |
height: 10px; | |
margin-left: -7px; | |
transform: rotate(45deg); | |
} | |
} | |
#counter{ | |
float:right | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment