const canvas = document.getElementById('wheel'); const ctx = canvas.getContext('2d'); const dpr = window.devicePixelRatio || 1; canvas.width = 400 * dpr; canvas.height = 400 * dpr; canvas.style.width = '400px'; canvas.style.height = '400px'; ctx.scale(dpr, dpr); const size = 400; const center = size / 2; let prizes = [ "10 Points", "50 Points", "100 Points", "Try Again", "Extra Life", "200 Points", "500 Points", "Jackpot!" ]; const palettes = { green: { borderColor: "#2e7d32", pointerColor: "#2e7d32", colors: [ "#a5d6a7", "#81c784", "#66bb6a", "#4caf50", "#388e3c", "#2e7d32", "#1b5e20", "#0d3d11" ], textColor: "#fff" }, gold: { borderColor: "#DAA520", pointerColor: "#DAA520", colors: [ "#FFD700", "#FFA500", "#B8860B", "#DAA520", "#FFD700", "#FFA500", "#B8860B", "#DAA520" ], textColor: "#000" }, pastel: { borderColor: "#FFC107", pointerColor: "#FFC107", colors: [ "#ffb3ba", "#bae1ff", "#baffc9", "#ffffba", "#ffb3ba", "#bae1ff", "#baffc9", "#ffffba" ], textColor: "#333" }, blueGradient: { borderColor: "#2962ff", pointerColor: "#2962ff", colors: [ "#2962ff", "#448aff", "#82b1ff", "#bbdefb", "#2962ff", "#448aff", "#82b1ff", "#bbdefb" ], textColor: "#fff" }, redfire: { borderColor: "#b71c1c", pointerColor: "#b71c1c", colors: [ "#d32f2f", "#f44336", "#e57373", "#ff8a80", "#d32f2f", "#f44336", "#e57373", "#ff8a80" ], textColor: "#fff" }, purpleDream: { borderColor: "#6a1b9a", pointerColor: "#6a1b9a", colors: [ "#8e24aa", "#ab47bc", "#ba68c8", "#ce93d8", "#8e24aa", "#ab47bc", "#ba68c8", "#ce93d8" ], textColor: "#fff" } }; const spinBtn = document.getElementById('spinBtn'); const stopBtn = document.getElementById('stopBtn'); const paletteSelect = document.getElementById('paletteSelect'); const entryList = document.getElementById('entryList'); const updateEntriesBtn = document.getElementById('updateEntriesBtn'); let currentPalette = 'green'; let rotation = 0; let isSpinning = false; let animationFrameId = null; let startTimestamp = null; let targetRotation = 0; let currentSpeed = 0; let decelerating = false; function applyPalette(paletteName) { currentPalette = paletteName; const pal = palettes[paletteName]; canvas.style.borderColor = pal.borderColor; // Redraw wheel and pointer drawRotatedWheel(rotation); } function drawWheel(pal) { ctx.clearRect(0, 0, size, size); const segmentCount = prizes.length; const segmentAngle = (2 * Math.PI) / segmentCount; for (let i = 0; i < segmentCount; i++) { const startAngle = i * segmentAngle; const endAngle = startAngle + segmentAngle; ctx.beginPath(); ctx.moveTo(center, center); ctx.arc(center, center, center - 10, startAngle, endAngle); ctx.closePath(); ctx.fillStyle = pal.colors[i % pal.colors.length]; ctx.fill(); ctx.save(); ctx.fillStyle = pal.textColor; ctx.translate(center, center); ctx.rotate(startAngle + segmentAngle / 2); ctx.textAlign = "right"; ctx.font = "bold 16px Arial"; ctx.fillText(prizes[i], center - 20, 10); ctx.restore(); } } function drawRotatedWheel(angleDegrees) { const angleRadians = angleDegrees * Math.PI / 180; ctx.clearRect(0, 0, size, size); ctx.save(); ctx.translate(center, center); ctx.rotate(angleRadians); ctx.translate(-center, -center); drawWheel(palettes[currentPalette]); ctx.restore(); drawPointer(); } function drawPointer() { const pal = palettes[currentPalette]; ctx.save(); ctx.translate(center, center); ctx.beginPath(); ctx.moveTo(center - 10, 0); ctx.lineTo(center + 15, -10); ctx.lineTo(center + 15, 10); ctx.closePath(); ctx.fillStyle = pal.pointerColor; ctx.shadowColor = 'rgba(0,0,0,0.2)'; ctx.shadowBlur = 4; ctx.fill(); ctx.restore(); } function showResult(rotationDegrees) { const segmentCount = prizes.length; const normalizedRotation = (rotationDegrees % 360 + 360) % 360; const pointerAngle = (360 - normalizedRotation) % 360; const segmentAngleSize = 360 / segmentCount; const segmentIndex = Math.floor(pointerAngle / segmentAngleSize); const result = prizes[segmentIndex]; const modal = document.getElementById('resultModal'); const resultText = document.getElementById('resultText'); const closeModal = document.getElementById('closeModal'); resultText.textContent = `You won: ${result}`; modal.style.display = 'flex'; closeModal.onclick = () => { modal.style.display = 'none'; }; window.onclick = (event) => { if (event.target === modal) { modal.style.display = 'none'; } }; } function spinStart() { if (isSpinning || prizes.length === 0) return; isSpinning = true; spinBtn.disabled = true; stopBtn.disabled = false; const spins = Math.floor(Math.random() * 4) + 5; const randomDegree = Math.random() * 360; targetRotation = spins * 360 + randomDegree; currentSpeed = 0; startTimestamp = null; decelerating = false; animationFrameId = requestAnimationFrame(spinAnimation); } function spinAnimation(timestamp) { if (!startTimestamp) startTimestamp = timestamp; if (!decelerating) { currentSpeed += 0.5; if (currentSpeed >= 30) { currentSpeed = 30; decelerating = true; } } else { currentSpeed -= 0.2; if (currentSpeed < 0.1) { currentSpeed = 0; finishSpin(); return; } } rotation += currentSpeed; rotation %= 360; drawRotatedWheel(rotation); animationFrameId = requestAnimationFrame(spinAnimation); } function stopSpin() { if (!isSpinning) return; decelerating = true; stopBtn.disabled = true; } function finishSpin() { cancelAnimationFrame(animationFrameId); isSpinning = false; spinBtn.disabled = false; stopBtn.disabled = true; showResult(rotation); } function updatePrizesFromInput() { const lines = entryList.value .split('\n') .map(line => line.trim()) .filter(line => line); if (lines.length === 0 || lines.length > 100) { alert("Please enter between 1 and 100 items."); return; } prizes = lines; rotation = 0; // Reset wheel position applyPalette(currentPalette); } // Button Actions document.getElementById('shuffleBtn').addEventListener('click', () => { const lines = entryList.value .split('\n') .map(line => line.trim()) .filter(line => line); for (let i = lines.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [lines[i], lines[j]] = [lines[j], lines[i]]; } entryList.value = lines.join('\n'); updatePrizesFromInput(); }); document.getElementById('sortBtn').addEventListener('click', () => { const lines = entryList.value .split('\n') .map(line => line.trim()) .filter(line => line) .sort((a, b) => a.localeCompare(b)); entryList.value = lines.join('\n'); updatePrizesFromInput(); }); document.getElementById('clearBtn').addEventListener('click', () => { entryList.value = ''; prizes = []; rotation = 0; applyPalette(currentPalette); }); // Event Listeners paletteSelect.addEventListener('change', () => { if (!isSpinning) { applyPalette(paletteSelect.value); } }); spinBtn.addEventListener('click', spinStart); stopBtn.addEventListener('click', stopSpin); updateEntriesBtn.addEventListener('click', updatePrizesFromInput); // Init applyPalette(currentPalette);