Building a Modern Interactive Raffle Wheel with HTML, CSS, and JavaScript

Linda Hamilton
Release: 2024-11-24 07:55:11
Original
458 people have browsed it

Building a Modern Interactive Raffle Wheel with HTML, CSS, and JavaScript

Introduction

In today's digital age, engaging your community with interactive tools is essential for fostering participation and excitement. Whether you're hosting a giveaway, conducting a poll, or organizing a competition, having a visually appealing and interactive raffle wheel can significantly enhance user experience. In this article, I'll walk you through the process of creating Modern Raffle 2024, an interactive raffle wheel built with HTML, CSS, and JavaScript. We'll cover everything from setting up the structure to adding animations and integrating social sharing features.

? Technologies Used

To bring this project to life, I leveraged the following technologies:

  • HTML5: For structuring the webpage and creating interactive elements.
  • CSS3: To style the application with modern design principles, including glassmorphism, animations, and responsive layouts.
  • JavaScript: To add interactivity, handle user inputs, and manage the raffle wheel's logic and animations.
  • Canvas API: For drawing and animating the raffle wheel.
  • Font Awesome: To incorporate vector icons for a polished look.
  • Google Fonts: Utilized the Inter font for a clean and modern typography.
  • Buy Me a Coffee: Integrated a donation button to support the project.

?️ Project Structure

The project is organized into three main files:

  1. index.html: Contains the HTML structure of the application.
  2. styles.css: Holds all the CSS styles for layout and design.
  3. script.js: Includes the JavaScript code that powers the interactivity and animations.

Additionally, a footer section is incorporated to promote my website, LinkedIn, Twitter, and include a Buy Me a Coffee button for support.

? HTML (index.html)

The HTML structure sets up the main components of the raffle application, including input sections for participants and prizes, the raffle wheel, a modal for announcing winners, and a footer for promotions.

Copy after login
Copy after login
Copy after login
Copy after login
Copy after login


html





Modern Raffle 2024








? Modern Raffle 2024 ?

    <div class="input-section">
        <h2>Add Participants</h2>
        <div class="input-group">
            <input type="text">


<pre class="brush:php;toolbar:false">
? CSS (styles.css)
The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.

Copy after login
Copy after login
Copy after login

/* Reset and Base Styles */

  • { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Inter', sans-serif; }

body {
background: linear-gradient(135deg, #1e3c72, #2a5298);
color: #ffffff;
display: flex;
flex-direction: column; /* Stack children vertically /
justify-content: flex-start; /
Start from the top /
align-items: center;
min-height: 100vh;
/
Remove overflow hidden to allow footer visibility */
overflow-x: hidden;
}

/* Container Styles /
.container {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
padding: 40px;
border-radius: 20px;
text-align: center;
width: 90%;
max-width: 900px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.37);
border: 1px solid rgba(255, 255, 255, 0.18);
animation: fadeIn 1s ease-in-out;
flex: 1; /
Allow container to grow and push footer down */
display: flex;
flex-direction: column;
align-items: center;
}

/* Fade-in Animation */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}

/* Heading Styles */
h1 {
margin-bottom: 30px;
font-size: 3rem;
font-weight: 700;
text-shadow: 3px 3px 6px rgba(0,0,0,0.3);
}

/* Input Sections */
.input-section {
margin-bottom: 40px;
width: 100%;
}

.input-section h2 {
margin-bottom: 15px;
font-size: 1.75rem;
font-weight: 600;
}

/* Input Groups */
.input-group {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin-bottom: 15px;
}

.input-group input {
padding: 12px 20px;
width: 60%;
border: none;
border-radius: 30px;
background: rgba(255, 255, 255, 0.1);
color: #ffffff;
font-size: 1rem;
outline: none;
transition: background 0.3s ease, box-shadow 0.3s ease;
}

.input-group input::placeholder {
color: #dddddd;
}

.input-group input:focus {
background: rgba(255, 255, 255, 0.2);
box-shadow: 0 0 10px rgba(255, 127, 80, 0.5);
}

.input-group button {
padding: 12px 25px;
border: none;
border-radius: 30px;
background-color: #ff7f50;
color: #fff;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
}

.input-group button:hover {
background-color: #ff5722;
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
}

/* User List */

userList {

Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

}

userList li {

    <div class="input-section">
        <h2>Add Participants</h2>
        <div class="input-group">
            <input type="text">


<pre class="brush:php;toolbar:false">
? CSS (styles.css)
The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.

Copy after login
Copy after login
Copy after login

}

/* Selected Prize */

selectedPrize {

list-style: none;
max-height: 120px;
overflow-y: auto;
text-align: left;
padding: 0 20%;
width: 100%;
Copy after login
Copy after login

}

/* Wheel Container */
.wheel-container {
position: relative;
margin-bottom: 40px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}

.wheel-wrapper {
position: relative;
width: 100%;
max-width: 500px;
margin: 0 auto 20px;
}

/* Canvas Styles */
canvas {
width: 100%;
height: auto;
border-radius: 50%;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
background: #000;
transition: transform 4s cubic-bezier(0.33, 1, 0.68, 1);
}

/* Pointer Styles */
.pointer {
position: absolute;
top: -20px;
left: 50%;
transform: translateX(-50%);
font-size: 2rem;
color: #ffeb3b;
animation: bounce 2s infinite;
}

@keyframes bounce {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}

/* Spin Button */

spinBtn {

padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
font-size: 1rem;
Copy after login
Copy after login

}

spinBtn:hover {

font-size: 1.2rem;
font-weight: 500;
margin-top: 10px;
Copy after login
Copy after login

}

spinBtn:active {

padding: 15px 35px;
border: none;
border-radius: 50px;
background-color: #32cd32;
color: #fff;
font-size: 1.25rem;
font-weight: 600;
cursor: pointer;
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
display: flex;
align-items: center;
gap: 10px;
margin: 0 auto;
Copy after login
Copy after login

}

/* Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.8);
animation: fadeInModal 0.5s ease;
}

@keyframes fadeInModal {
from { opacity: 0; }
to { opacity: 1; }
}

.modal-content {
background-color: rgba(30, 30, 30, 0.95);
margin: 10% auto;
padding: 30px;
border-radius: 15px;
width: 90%;
max-width: 600px;
text-align: center;
box-shadow: 0 8px 25px rgba(0,0,0,0.5);
position: relative;
animation: slideDown 0.5s ease;
}

@keyframes slideDown {
from { transform: translateY(-50px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}

.close-button {
color: #bbb;
position: absolute;
top: 15px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
}

.close-button:hover,
.close-button:focus {
color: #fff;
}

.modal-content h2 {
margin-bottom: 20px;
font-size: 2rem;
font-weight: 700;
}

.modal-content p {
font-size: 1.25rem;
margin-bottom: 25px;
}

shareBtn {

background-color: #28a428;
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(0,0,0,0.4);
Copy after login
Copy after login

}

shareBtn:hover {

transform: translateY(0);
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
Copy after login

}

/* Footer Styles /
.footer {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
padding: 20px 0;
border-top: 1px solid rgba(255, 255, 255, 0.2);
width: 100%;
/
Ensure footer stays below content */
flex-shrink: 0;
}

.footer-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 900px;
margin: 0 auto;
padding: 0 20px;
}

.footer-links {
display: flex;
gap: 20px;
margin-bottom: 15px;
}

.footer-links a {
color: #ffffff;
font-size: 1rem;
text-decoration: none;
display: flex;
align-items: center;
gap: 8px;
transition: color 0.3s ease, transform 0.2s ease;
}

.footer-links a:hover {
color: #ff7f50;
transform: translateY(-2px);
}

.footer-links a i {
font-size: 1.2rem;
}

.footer-donate {
margin-top: 10px;
}

/* Responsive Design for Footer */
@media (min-width: 600px) {
.footer-container {
flex-direction: row;
justify-content: space-between;
}

Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

}

/* Scrollbar Styles for User List */

userList::-webkit-scrollbar {

    <div class="input-section">
        <h2>Add Participants</h2>
        <div class="input-group">
            <input type="text">


<pre class="brush:php;toolbar:false">
? CSS (styles.css)
The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.

Copy after login

}

userList::-webkit-scrollbar-track {

list-style: none;
max-height: 120px;
overflow-y: auto;
text-align: left;
padding: 0 20%;
width: 100%;
Copy after login
Copy after login

}

userList::-webkit-scrollbar-thumb {

padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
font-size: 1rem;
Copy after login
Copy after login

}

userList::-webkit-scrollbar-thumb:hover {

font-size: 1.2rem;
font-weight: 500;
margin-top: 10px;
Copy after login
Copy after login

}

/* Button Focus States for Accessibility */
.input-group button:focus,

spinBtn:focus,

shareBtn:focus {

padding: 15px 35px;
border: none;
border-radius: 50px;
background-color: #32cd32;
color: #fff;
font-size: 1.25rem;
font-weight: 600;
cursor: pointer;
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
display: flex;
align-items: center;
gap: 10px;
margin: 0 auto;
Copy after login
Copy after login

}

background-color: #28a428;
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(0,0,0,0.4);
Copy after login
Copy after login

// Selecting DOM Elements
const addUserBtn = document.getElementById('addUserBtn');
const usernameInput = document.getElementById('username');
const userList = document.getElementById('userList');
const setPrizeBtn = document.getElementById('setPrizeBtn');
const prizeInput = document.getElementById('prize');
const selectedPrize = document.getElementById('selectedPrize');
const spinBtn = document.getElementById('spinBtn');
const winnerModal = document.getElementById('winnerModal');
const closeBtn = document.querySelector('.close-button');
const winnerText = document.getElementById('winnerText');
const shareBtn = document.getElementById('shareBtn');

// State Variables
let users = [];
let prize = "None";
let isSpinning = false;

// Wheel Configuration
const canvas = document.getElementById('raffleWheel');
const ctx = canvas.getContext('2d');
const wheelRadius = canvas.width / 2;
const colors = ['#FF5733', '#33FF57', '#3357FF', '#F333FF', '#FF33A8', '#33FFF6', '#FFC300', '#DAF7A6'];
let startAngle = 0;
let arc = 0;

// Initialize Wheel
function initializeWheel() {
if (users.length === 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
return;
}
arc = (2 * Math.PI) / users.length;
drawWheel();
}

// Draw the Raffle Wheel
function drawWheel() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < users.length; i ) {
const angle = startAngle i * arc;
ctx.fillStyle = colors[i % colors.length];
ctx.beginPath();
ctx.moveTo(wheelRadius, wheelRadius);
ctx.arc(wheelRadius, wheelRadius, wheelRadius, angle, angle arc, false);
ctx.closePath();
ctx.fill();

Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

}

// Draw the Pointer Arrow
function drawPointer() {
const pointerSize = 20;
ctx.fillStyle = '#FFEB3B';
ctx.beginPath();
ctx.moveTo(wheelRadius - pointerSize, 0);
ctx.lineTo(wheelRadius pointerSize, 0);
ctx.lineTo(wheelRadius, -pointerSize * 1.5);
ctx.closePath();
ctx.fill();
}

// Add User Event
addUserBtn.addEventListener('click', addUser);
usernameInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') addUser();
});

// Function to Add a User
function addUser() {
const username = usernameInput.value.trim();
if (username === "") {
showAlert("Please enter a valid username.");
return;
}
if (users.includes(username)) {
showAlert("This username is already added.");
return;
}
users.push(username);
updateUserList();
usernameInput.value = '';
initializeWheel();
}

// Update the User List UI
function updateUserList() {
userList.innerHTML = '';
users.forEach(user => {
const li = document.createElement('li');
li.textContent = user;
userList.appendChild(li);
});
}

// Set Prize Event
setPrizeBtn.addEventListener('click', setPrize);
prizeInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') setPrize();
});

// Function to Set the Prize
function setPrize() {
const prizeInputValue = prizeInput.value.trim();
if (prizeInputValue === "") {
showAlert("Please enter a valid prize.");
return;
}
prize = prizeInputValue;
selectedPrize.textContent = Selected Prize: ${prize};
prizeInput.value = '';
}

// Spin Button Event
spinBtn.addEventListener('click', spinWheel);

// Function to Spin the Wheel
function spinWheel() {
if (isSpinning) return;
if (users.length === 0) {
showAlert("Please add at least one user.");
return;
}
if (prize === "None") {
showAlert("Please set a prize.");
return;
}

Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

}

// Function to Stop the Wheel and Announce Winner
function stopRotateWheel() {
const degrees = startAngle * 180 / Math.PI 90;
const arcd = arc * 180 / Math.PI;
const index = Math.floor((360 - (degrees % 360)) / arcd) % users.length;
const winner = users[index];
showWinner(winner);
isSpinning = false;
spinBtn.disabled = false;
}

// Easing Function for Smooth Animation
function easeOut(t, b, c, d) {
t /= d;
t--;
return c * (t * t * t 1) b;
}

// Function to Display Alerts
function showAlert(message) {
alert(message);
}

// Function to Show Winner in Modal
function showWinner(winner) {
winnerText.textContent = ${winner} has won ${prize}! ?;
winnerModal.style.display = "block";
}

// Close Modal Events
closeBtn.addEventListener('click', () => {
winnerModal.style.display = "none";
});
window.addEventListener('click', (event) => {
if (event.target === winnerModal) {
winnerModal.style.display = "none";
}
});

// Share on Twitter
shareBtn.addEventListener('click', shareOnTwitter);

// Function to Share Winner on Twitter
function shareOnTwitter() {
const text = encodeURIComponent(? Congratulations to ${winnerText.textContent}! They have won ${prize}! ? #Giveaway #Community);
const url = encodeURIComponent('https://gladiatorsbattle.com');
const twitterUrl = https://twitter.com/intent/tweet?text=${text}&url=${url};
window.open(twitterUrl, '_blank');
}

// Initial Wheel Setup
initializeWheel();

    <div class="input-section">
        <h2>Add Participants</h2>
        <div class="input-group">
            <input type="text">


<pre class="brush:php;toolbar:false">
? CSS (styles.css)
The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.

Copy after login
Copy after login
Copy after login

The above is the detailed content of Building a Modern Interactive Raffle Wheel with HTML, CSS, and JavaScript. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template