はじめに
今日のデジタル時代では、参加と興奮を促進するには、インタラクティブなツールを使ってコミュニティに参加することが不可欠です。プレゼントを主催する場合でも、投票を実施する場合でも、コンテストを企画する場合でも、視覚的に魅力的でインタラクティブな抽選ホイールを使用すると、ユーザー エクスペリエンスが大幅に向上します。この記事では、HTML、CSS、および で構築されたインタラクティブな抽選ホイールである Modern Raffle 2024 を作成するプロセスについて説明します。 JavaScript。構造のセットアップからアニメーションの追加、ソーシャル共有機能の統合まで、すべてをカバーします。
このプロジェクトを実現するために、次のテクノロジーを活用しました:
プロジェクトは 3 つの主要なファイルで構成されています:
さらに、私の Web サイト、LinkedIn、Twitter を宣伝するために フッター セクションが組み込まれており、サポートのための Buy Me a Coffee ボタンが含まれています。
HTML 構造は、参加者と賞品の入力セクション、抽選ホイール、勝者を発表するモーダル、プロモーション用のフッターなど、抽選アプリケーションの主要コンポーネントを設定します。
html
<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.
/* スタイルのリセットと基本スタイル */
ボディ{
背景: 線形グラデーション(135度, #1e3c72, #2a5298);
色: #ffffff;
表示: フレックス;
フレックス方向: 列; /* 子を垂直方向に積み重ねます /
justify-content: flex-start; / 上から開始 /
align-items: center;
最小高さ: 100vh;
/ フッターを表示できるようにオーバーフローの非表示を削除 */
オーバーフロー-x: 非表示;
}
/* コンテナ スタイル /
.container {
背景: rgba(255, 255, 255, 0.05);
背景フィルター:blur(10px);
パディング: 40px;
境界半径: 20px;
text-align: 中央;
幅: 90%;
最大幅: 900px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.37);
ボーダー: 1px ソリッド rgba(255, 255, 255, 0.18);
アニメーション: フェードイン 1 秒イーズインアウト;
フレックス: 1; / コンテナーの成長を許可し、フッターを下に押し込みます */
表示: フレックス;
フレックス方向: 列;
align-items: center;
}
/* フェードイン アニメーション */
@keyframes fadeIn {
から { 不透明度: 0;変換:translateY(-20px); }
{ 不透明度: 1;変換:translateY(0); }
}
/* 見出しスタイル */
h1 {
margin-bottom: 30px;
フォントサイズ: 3rem;
フォントの太さ: 700;
text-shadow: 3px 3px 6px rgba(0,0,0,0.3);
}
/* 入力セクション */
.input-section {
margin-bottom: 40px;
幅: 100%;
}
.input-section h2 {
margin-bottom: 15px;
フォントサイズ: 1.75rem;
フォントの太さ: 600;
}
/* 入力グループ */
.input-group {
表示: フレックス;
justify-content: center;
align-items: center;
ギャップ: 10px;
margin-bottom: 15px;
}
.input-group input {
パディング: 12px 20px;
幅: 60%;
境界線: なし;
境界半径: 30px;
背景: rgba(255, 255, 255, 0.1);
色: #ffffff;
フォントサイズ: 1rem;
概要: なし;
トランジション: 背景 0.3 秒イーズ、ボックスシャドウ 0.3 秒イーズ;
}
.input-group input::placeholder {
色: #dddddd;
}
.input-group input:focus {
背景: rgba(255, 255, 255, 0.2);
box-shadow: 0 0 10px rgba(255, 127, 80, 0.5);
}
.input-group ボタン {
パディング: 12px 25px;
境界線: なし;
境界半径: 30px;
背景色: #ff7f50;
色: #fff;
フォントサイズ: 1rem;
フォントの太さ: 600;
カーソル: ポインタ;
表示: フレックス;
align-items: center;
ギャップ: 8px;
トランジション: 背景色 0.3 秒イーズ、変換 0.2 秒イーズ、ボックスシャドウ 0.3 秒イーズ;
}
.input-group button:hover {
背景色: #ff5722;
変換:translateY(-2px);
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
}
/* ユーザーリスト */
}
<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.
}
/* 選ばれた賞品 */
list-style: none; max-height: 120px; overflow-y: auto; text-align: left; padding: 0 20%; width: 100%;
}
/* ホイールコンテナ */
.wheel-container {
位置: 相対;
margin-bottom: 40px;
幅: 100%;
表示: フレックス;
フレックス方向: 列;
align-items: center;
}
.wheel-wrapper {
位置: 相対;
幅: 100%;
最大幅: 500px;
マージン: 0 自動 20px;
}
/* キャンバス スタイル */
キャンバス {
幅: 100%;
高さ: 自動;
境界半径: 50%;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
背景: #000;
遷移: 変換 4s cubic-bezier(0.33, 1, 0.68, 1);
}
/* ポインター スタイル */
.pointer {
位置: 絶対;
上: -20px;
左: 50%;
変換:translateX(-50%);
フォントサイズ: 2rem;
色: #ffeb3b;
アニメーション: 2 秒間無限にバウンス;
}
@keyframes バウンス {
0%、100% { 変換: 変換X(-50%) 変換Y(0); }
50% { 変換: 変換X(-50%) 変換Y(-10px); }
}
/* スピンボタン */
padding: 8px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.2); font-size: 1rem;
}
font-size: 1.2rem; font-weight: 500; margin-top: 10px;
}
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;
}
/* モーダル スタイル */
.modal {
表示: なし。
位置: 固定;
z インデックス: 100;
左: 0;
上: 0;
幅: 100%;
高さ: 100%;
オーバーフロー: 自動;
背景色: rgba(0,0,0,0.8);
アニメーション: fadeInModal 0.5 秒の容易さ;
}
@keyframes fadeInModal {
から { 不透明度: 0; }
{ 不透明度: 1; }
}
.modal-content {
背景色: rgba(30, 30, 30, 0.95);
マージン: 10% 自動;
パディング: 30px;
境界半径: 15px;
幅: 90%;
最大幅: 600px;
text-align: 中央;
box-shadow: 0 8px 25px rgba(0,0,0,0.5);
位置: 相対;
アニメーション: slideDown 0.5 秒の容易さ;
}
@keyframes slideDown {
{ 変換:translateY(-50px); から不透明度: 0; }
に { 変換:translateY(0);不透明度: 1; }
}
.close-button {
色: #bbb;
位置: 絶対;
上: 15px;
右: 20px;
フォントサイズ: 28px;
フォントの太さ: 太字;
カーソル: ポインタ;
トランジション: カラー 0.3 秒イーズ;
}
.close-button:hover,
.close-button:focus {
色: #fff;
}
.modal-content h2 {
margin-bottom: 20px;
フォントサイズ: 2rem;
フォントの太さ: 700;
}
.modal-content p {
フォントサイズ: 1.25rem;
margin-bottom: 25px;
}
background-color: #28a428; transform: translateY(-3px); box-shadow: 0 8px 25px rgba(0,0,0,0.4);
}
transform: translateY(0); box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
/* フッタースタイル /
.footer {
背景: rgba(255, 255, 255, 0.05);
背景フィルター:blur(10px);
パディング: 20px 0;
border-top: 1px ソリッド rgba(255, 255, 255, 0.2);
幅: 100%;
/ フッターがコンテンツの下にあることを確認します */
フレックスシュリンク: 0;
}
.footer-container {
表示: フレックス;
フレックス方向: 列;
align-items: center;
justify-content: center;
最大幅: 900px;
マージン: 0 自動;
パディング: 0 20px;
}
.footer-links {
表示: フレックス;
ギャップ: 20px;
margin-bottom: 15px;
}
.footer-links a {
色: #ffffff;
フォントサイズ: 1rem;
テキスト装飾: なし;
表示: フレックス;
align-items: center;
ギャップ: 8px;
トランジション: カラー 0.3 秒の容易さ、変換 0.2 秒の容易さ;
}
.footer-links a:hover {
色: #ff7f50;
変換:translateY(-2px);
}
.footer-links a i {
フォントサイズ: 1.2rem;
}
.footer-donate {
margin-top: 10px;
}
/* フッターのレスポンシブ デザイン */
@media (最小幅: 600px) {
.footer-container {
フレックス方向: 行;
justify-content: space-between;
}
}
/* ユーザーリストのスクロールバースタイル */
<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.
}
list-style: none; max-height: 120px; overflow-y: auto; text-align: left; padding: 0 20%; width: 100%;
}
padding: 8px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.2); font-size: 1rem;
}
font-size: 1.2rem; font-weight: 500; margin-top: 10px;
}
/* アクセシビリティのためのボタンのフォーカス状態 */
.input-group ボタン:フォーカス、
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;
}
background-color: #28a428; transform: translateY(-3px); box-shadow: 0 8px 25px rgba(0,0,0,0.4);
// DOM 要素の選択
const addUserBtn = document.getElementById('addUserBtn');
const usernameInput = document.getElementById('username');
const userList = document.getElementById('userList');
const setPrizeBtn = document.getElementById('setPrizeBtn');
const awardInput = document.getElementById('賞');
const selectedPrize = document.getElementById('selectedPrize');
const pinBtn = document.getElementById('spinBtn');
const winnerModal = document.getElementById('winnerModal');
const closeBtn = document.querySelector('.close-button');
const winnerText = document.getElementById('winnerText');
const shareBtn = document.getElementById('shareBtn');
// 状態変数
let users = [];
let 賞品 = "なし";
let isSpinning = false;
// ホイール構成
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'];
startAngle = 0 にします;
円弧 = 0 にします;
// ホイールを初期化します
関数initializeWheel() {
if (users.length === 0) {
ctx.clearRect(0, 0, Canvas.width, Canvas.height);
戻る;
}
arc = (2 * Math.PI) / users.length;
drawWheel();
}
// ラッフルホイールを引く
関数drawWheel() {
ctx.clearRect(0, 0, Canvas.width, Canvas.height);
for (let i = 0; i
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();
}
// ポインタ矢印を描画します
functiondrawPointer() {
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();
}
// ユーザーイベントを追加
addUserBtn.addEventListener('click', addUser);
usernameInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') addUser();
});
// ユーザーを追加する関数
function addUser() {
const ユーザー名 = ユーザー名Input.value.trim();
if (ユーザー名 === "") {
showAlert("有効なユーザー名を入力してください。");
戻る;
}
if (users.includes(ユーザー名)) {
showAlert("このユーザー名はすでに追加されています。");
戻る;
}
users.push(ユーザー名);
updateUserList();
ユーザー名入力.値 = '';
初期化ホイール();
}
// ユーザーリスト UI を更新します
function updateUserList() {
userList.innerHTML = '';
users.forEach(user => {
const li = document.createElement('li');
li.textContent = ユーザー;
userList.appendChild(li);
});
}
// 賞品イベントを設定
setPrizeBtn.addEventListener('click', setPrize);
priorityInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') setPrize();
});
// 賞品を設定する関数
function setPrize() {
const priorityInputValue = priorityInput.value.trim();
if (prizeInputValue === "") {
showAlert("有効な賞品を入力してください。");
戻る;
}
賞品 = 賞品入力値;
selectedPrize.textContent = 選択された賞品: ${prize};
賞品入力.値 = '';
}
// スピンボタンイベント
スピンBtn.addEventListener('クリック', スピンホイール);
// ホイールを回転させる関数
関数スピンホイール() {
if (isSpinning) return;
if (users.length === 0) {
showAlert("少なくとも 1 人のユーザーを追加してください。");
戻る;
}
if (賞品 === "なし") {
showAlert("賞品を設定してください。");
戻る;
}
}
// ホイールを停止して勝者を発表する関数
関数 stopRotateWheel() {
const 度 = startAngle * 180 / Math.PI 90;
const arcd = arc * 180 / Math.PI;
const Index = Math.floor((360 - (度 % 360)) / arcd) % users.length;
const 勝者 = ユーザー[インデックス];
showWinner(勝者);
isSpinning = false;
pinBtn.disabled = false;
}
// スムーズなアニメーションのためのイージング関数
functioneaseOut(t, b, c, d) {
t /= d;
t--;
return c * (t * t * t 1) b;
}
// アラートを表示する関数
function showAlert(message) {
アラート(メッセージ);
}
// モーダルで勝者を表示する関数
関数 showWinner(勝者) {
winnerText.textContent = ${winner} が ${prize} を獲得しました! ?;
勝者Modal.style.display = "ブロック";
}
// モーダルイベントを閉じる
closeBtn.addEventListener('click', () => {
勝者Modal.style.display = "なし";
});
window.addEventListener('click', (イベント) => {
if (event.target ===勝者Modal) {
勝者Modal.style.display = "なし";
}
});
// Twitter でシェア
shareBtn.addEventListener('click', shareOnTwitter);
// 当選者をTwitterで共有する機能
関数 shareOnTwitter() {
const text = encodeURIComponent(? ${winnerText.textContent} さん、おめでとうございます! ${賞} を獲得しました! ? #Giveaway #Community);
const url = encodeURIComponent('https://gladiatorsbattle.com');
const twitterUrl = https://twitter.com/intent/tweet?text=${text}&url=${url};
window.open(twitterUrl, '_blank');
}
// ホイールの初期セットアップ
初期化ホイール();
<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.
以上がHTML、CSS、JavaScript を使用して最新のインタラクティブな抽選ホイールを構築するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。