洛阳市本地信息网

如何使用HTML+JavaScript实现积分抽奖系统

2026-04-10 07:44:03 浏览次数:1
详细信息

HTML+JavaScript积分抽奖系统

我将设计一个完整的积分抽奖系统,包含用户积分管理、抽奖转盘、中奖记录和积分消耗等功能。

设计思路

用户界面:显示当前积分、抽奖转盘、奖品列表 积分系统:模拟积分获取和消耗 抽奖逻辑:转盘旋转动画和随机奖品分配 中奖记录:保存并显示历史中奖信息

实现代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>积分抽奖系统</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        }

        body {
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            color: #333;
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            text-align: center;
            margin-bottom: 30px;
            color: white;
        }

        h1 {
            font-size: 2.8rem;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
        }

        .subtitle {
            font-size: 1.2rem;
            opacity: 0.9;
        }

        .dashboard {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
            margin-bottom: 30px;
        }

        .card {
            background: white;
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
            flex: 1;
            min-width: 280px;
        }

        .card h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 2px solid #f0f0f0;
            font-size: 1.6rem;
        }

        .points-display {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }

        .points-value {
            font-size: 3.5rem;
            font-weight: bold;
            color: #e74c3c;
            text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
        }

        .points-label {
            font-size: 1.2rem;
            color: #7f8c8d;
        }

        .action-buttons {
            display: flex;
            gap: 15px;
            margin-top: 15px;
        }

        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 50px;
            font-size: 1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            flex: 1;
        }

        .btn-primary {
            background: linear-gradient(to right, #3498db, #2980b9);
            color: white;
        }

        .btn-success {
            background: linear-gradient(to right, #2ecc71, #27ae60);
            color: white;
        }

        .btn-warning {
            background: linear-gradient(to right, #f39c12, #e67e22);
            color: white;
        }

        .btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }

        .btn:active {
            transform: translateY(0);
        }

        .btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }

        .roulette-container {
            position: relative;
            width: 400px;
            height: 400px;
            margin: 0 auto 30px;
        }

        .roulette {
            width: 100%;
            height: 100%;
            border-radius: 50%;
            position: relative;
            overflow: hidden;
            box-shadow: 0 0 30px rgba(0, 0, 0, 0.2);
            background: #f8f9fa;
            transition: transform 5s cubic-bezier(0.17, 0.67, 0.24, 0.99);
        }

        .roulette-slice {
            position: absolute;
            width: 50%;
            height: 50%;
            transform-origin: bottom right;
            left: 0;
            top: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            overflow: hidden;
        }

        .slice-content {
            position: absolute;
            width: 70%;
            left: 0;
            text-align: center;
            transform-origin: center;
            transform: rotate(45deg);
            font-weight: 600;
            color: white;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
        }

        .roulette-center {
            position: absolute;
            width: 80px;
            height: 80px;
            background: white;
            border-radius: 50%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 10;
            box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            color: #2c3e50;
            cursor: pointer;
            border: 5px solid #3498db;
        }

        .roulette-pointer {
            position: absolute;
            top: -30px;
            left: 50%;
            transform: translateX(-50%);
            width: 40px;
            height: 60px;
            z-index: 20;
        }

        .pointer-triangle {
            width: 0;
            height: 0;
            border-left: 20px solid transparent;
            border-right: 20px solid transparent;
            border-top: 30px solid #e74c3c;
        }

        .prize-list {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
            gap: 15px;
            margin-top: 15px;
        }

        .prize-item {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 10px;
            text-align: center;
            border-left: 5px solid #3498db;
            transition: transform 0.3s;
        }

        .prize-item:hover {
            transform: translateY(-5px);
            box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
        }

        .prize-name {
            font-weight: 600;
            margin-bottom: 5px;
            color: #2c3e50;
        }

        .prize-points {
            color: #e74c3c;
            font-weight: bold;
        }

        .history-list {
            max-height: 300px;
            overflow-y: auto;
            margin-top: 15px;
        }

        .history-item {
            padding: 12px 15px;
            background: #f8f9fa;
            margin-bottom: 10px;
            border-radius: 8px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-left: 4px solid #2ecc71;
        }

        .history-prize {
            font-weight: 600;
        }

        .history-date {
            color: #7f8c8d;
            font-size: 0.9rem;
        }

        .result-modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            z-index: 100;
            align-items: center;
            justify-content: center;
        }

        .modal-content {
            background: white;
            padding: 40px;
            border-radius: 20px;
            text-align: center;
            max-width: 500px;
            width: 90%;
            animation: modalAppear 0.5s;
        }

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

        .result-icon {
            font-size: 4rem;
            margin-bottom: 20px;
        }

        .success-icon {
            color: #2ecc71;
        }

        .fail-icon {
            color: #e74c3c;
        }

        .result-text {
            font-size: 1.8rem;
            margin-bottom: 10px;
            color: #2c3e50;
        }

        .result-details {
            color: #7f8c8d;
            margin-bottom: 25px;
            font-size: 1.1rem;
        }

        .close-modal {
            background: #3498db;
            color: white;
            border: none;
            padding: 12px 30px;
            border-radius: 50px;
            font-size: 1rem;
            cursor: pointer;
            font-weight: 600;
        }

        footer {
            text-align: center;
            color: white;
            margin-top: 40px;
            opacity: 0.8;
            font-size: 0.9rem;
        }

        @media (max-width: 768px) {
            .dashboard {
                flex-direction: column;
            }

            .roulette-container {
                width: 300px;
                height: 300px;
            }

            h1 {
                font-size: 2.2rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>积分抽奖系统</h1>
            <p class="subtitle">消耗积分参与抽奖,赢取丰富奖品</p>
        </header>

        <div class="dashboard">
            <div class="card">
                <h2>我的积分</h2>
                <div class="points-display">
                    <div>
                        <div class="points-label">当前积分</div>
                        <div class="points-value" id="pointsValue">0</div>
                    </div>
                    <div>
                        <div class="points-label">已抽奖次数</div>
                        <div class="points-value" style="font-size: 2.5rem;" id="drawCount">0</div>
                    </div>
                </div>
                <p style="color: #7f8c8d; margin-bottom: 15px;">每次抽奖消耗 <strong>100积分</strong></p>
                <div class="action-buttons">
                    <button class="btn btn-success" id="addPoints">获取积分 (+100)</button>
                    <button class="btn btn-warning" id="resetPoints">重置积分</button>
                </div>
            </div>

            <div class="card">
                <h2>抽奖转盘</h2>
                <div class="roulette-container">
                    <div class="roulette" id="roulette">
                        <!-- 转盘切片通过JS动态生成 -->
                    </div>
                    <div class="roulette-pointer">
                        <div class="pointer-triangle"></div>
                    </div>
                    <div class="roulette-center" id="spinButton">
                        开始抽奖
                    </div>
                </div>
                <div style="text-align: center;">
                    <button class="btn btn-primary" id="drawBtn" style="width: 200px;">消耗100积分抽奖</button>
                </div>
            </div>
        </div>

        <div class="dashboard">
            <div class="card">
                <h2>奖品列表</h2>
                <div class="prize-list" id="prizeList">
                    <!-- 奖品列表通过JS动态生成 -->
                </div>
            </div>

            <div class="card">
                <h2>中奖记录</h2>
                <div class="history-list" id="historyList">
                    <!-- 中奖记录通过JS动态生成 -->
                </div>
                <div class="action-buttons" style="margin-top: 20px;">
                    <button class="btn btn-warning" id="clearHistory">清空记录</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 抽奖结果弹窗 -->
    <div class="result-modal" id="resultModal">
        <div class="modal-content">
            <div class="result-icon success-icon" id="resultIcon">🎁</div>
            <div class="result-text" id="resultText">恭喜中奖!</div>
            <div class="result-details" id="resultDetails">您获得了:一等奖</div>
            <button class="close-modal" id="closeModal">确定</button>
        </div>
    </div>

    <footer>
        <p>积分抽奖系统 &copy; 2023 | 每次抽奖消耗100积分</p>
    </footer>

    <script>
        // 奖品数据
        const prizes = [
            { id: 1, name: "一等奖", description: "高级蓝牙耳机", color: "#FF6B6B", probability: 5, pointsCost: 100 },
            { id: 2, name: "二等奖", description: "智能手环", color: "#4ECDC4", probability: 10, pointsCost: 100 },
            { id: 3, name: "三等奖", description: "移动电源", color: "#FFD166", probability: 15, pointsCost: 100 },
            { id: 4, name: "四等奖", description: "U盘 32GB", color: "#06D6A0", probability: 20, pointsCost: 100 },
            { id: 5, name: "五等奖", description: "咖啡券", color: "#118AB2", probability: 25, pointsCost: 100 },
            { id: 6, name: "谢谢参与", description: "下次好运", color: "#9D9D9D", probability: 25, pointsCost: 100 }
        ];

        // 初始化数据
        let userPoints = 500; // 初始积分
        let drawCount = 0; // 抽奖次数
        let isSpinning = false; // 转盘是否在旋转中
        let history = []; // 中奖记录

        // DOM元素
        const pointsValueEl = document.getElementById('pointsValue');
        const drawCountEl = document.getElementById('drawCount');
        const rouletteEl = document.getElementById('roulette');
        const spinButtonEl = document.getElementById('spinButton');
        const drawBtn = document.getElementById('drawBtn');
        const addPointsBtn = document.getElementById('addPoints');
        const resetPointsBtn = document.getElementById('resetPoints');
        const prizeListEl = document.getElementById('prizeList');
        const historyListEl = document.getElementById('historyList');
        const resultModal = document.getElementById('resultModal');
        const resultText = document.getElementById('resultText');
        const resultDetails = document.getElementById('resultDetails');
        const resultIcon = document.getElementById('resultIcon');
        const closeModalBtn = document.getElementById('closeModal');
        const clearHistoryBtn = document.getElementById('clearHistory');

        // 初始化函数
        function init() {
            updatePointsDisplay();
            createRouletteSlices();
            createPrizeList();
            loadHistory();
            updateHistoryDisplay();

            // 绑定事件
            spinButtonEl.addEventListener('click', startSpin);
            drawBtn.addEventListener('click', startSpin);
            addPointsBtn.addEventListener('click', addPoints);
            resetPointsBtn.addEventListener('click', resetPoints);
            closeModalBtn.addEventListener('click', closeResultModal);
            clearHistoryBtn.addEventListener('click', clearHistory);

            // 点击弹窗外关闭弹窗
            resultModal.addEventListener('click', function(e) {
                if (e.target === resultModal) {
                    closeResultModal();
                }
            });
        }

        // 更新积分显示
        function updatePointsDisplay() {
            pointsValueEl.textContent = userPoints;
            drawCountEl.textContent = drawCount;

            // 根据积分是否足够设置抽奖按钮状态
            if (userPoints < 100 || isSpinning) {
                drawBtn.disabled = true;
                spinButtonEl.style.cursor = 'not-allowed';
            } else {
                drawBtn.disabled = false;
                spinButtonEl.style.cursor = 'pointer';
            }
        }

        // 创建转盘切片
        function createRouletteSlices() {
            rouletteEl.innerHTML = '';
            const sliceAngle = 360 / prizes.length;

            prizes.forEach((prize, index) => {
                const slice = document.createElement('div');
                slice.className = 'roulette-slice';
                slice.style.backgroundColor = prize.color;
                slice.style.transform = `rotate(${index * sliceAngle}deg)`;

                const sliceContent = document.createElement('div');
                sliceContent.className = 'slice-content';
                sliceContent.style.transform = `rotate(${sliceAngle/2}deg)`;
                sliceContent.innerHTML = `<div style="font-size: 16px; margin-bottom: 5px;">${prize.name}</div><div style="font-size: 12px;">${prize.description}</div>`;

                slice.appendChild(sliceContent);
                rouletteEl.appendChild(slice);
            });
        }

        // 创建奖品列表
        function createPrizeList() {
            prizeListEl.innerHTML = '';

            prizes.forEach(prize => {
                const prizeItem = document.createElement('div');
                prizeItem.className = 'prize-item';
                prizeItem.style.borderLeftColor = prize.color;
                prizeItem.innerHTML = `
                    <div class="prize-name">${prize.name}</div>
                    <div>${prize.description}</div>
                    <div class="prize-points">中奖概率: ${prize.probability}%</div>
                `;

                prizeListEl.appendChild(prizeItem);
            });
        }

        // 添加积分
        function addPoints() {
            userPoints += 100;
            updatePointsDisplay();
        }

        // 重置积分
        function resetPoints() {
            if (confirm("确定要重置积分吗?这将清空您的积分和抽奖次数。")) {
                userPoints = 500;
                drawCount = 0;
                updatePointsDisplay();
            }
        }

        // 开始抽奖
        function startSpin() {
            if (isSpinning) return;

            // 检查积分是否足够
            if (userPoints < 100) {
                alert("积分不足!请获取更多积分。");
                return;
            }

            // 扣除积分
            userPoints -= 100;
            drawCount++;
            updatePointsDisplay();

            // 设置旋转状态
            isSpinning = true;
            spinButtonEl.textContent = "抽奖中...";
            spinButtonEl.style.pointerEvents = "none";

            // 随机选择奖品(基于概率)
            const randomNum = Math.random() * 100;
            let cumulativeProbability = 0;
            let selectedPrize = null;

            for (const prize of prizes) {
                cumulativeProbability += prize.probability;
                if (randomNum <= cumulativeProbability) {
                    selectedPrize = prize;
                    break;
                }
            }

            // 计算旋转角度(确保指针停在所选奖品上)
            const prizeIndex = prizes.findIndex(p => p.id === selectedPrize.id);
            const sliceAngle = 360 / prizes.length;
            const targetRotation = 3600 + (360 - (prizeIndex * sliceAngle) - sliceAngle / 2);

            // 应用旋转动画
            rouletteEl.style.transform = `rotate(${targetRotation}deg)`;

            // 抽奖结果
            setTimeout(() => {
                isSpinning = false;
                spinButtonEl.textContent = "开始抽奖";
                spinButtonEl.style.pointerEvents = "auto";

                // 保存到历史记录
                const historyItem = {
                    prize: selectedPrize.name,
                    description: selectedPrize.description,
                    date: new Date().toLocaleString()
                };

                history.unshift(historyItem);
                saveHistory();
                updateHistoryDisplay();

                // 显示结果弹窗
                showResultModal(selectedPrize);
            }, 5000);
        }

        // 显示结果弹窗
        function showResultModal(prize) {
            resultText.textContent = prize.name === "谢谢参与" ? "很遗憾,未中奖" : "恭喜中奖!";
            resultDetails.textContent = prize.name === "谢谢参与" 
                ? "感谢参与,下次好运!" 
                : `您获得了:${prize.description}`;

            resultIcon.textContent = prize.name === "谢谢参与" ? "😢" : "🎁";
            resultIcon.className = prize.name === "谢谢参与" ? "result-icon fail-icon" : "result-icon success-icon";

            resultModal.style.display = "flex";
        }

        // 关闭结果弹窗
        function closeResultModal() {
            resultModal.style.display = "none";
        }

        // 保存历史记录到本地存储
        function saveHistory() {
            localStorage.setItem('lotteryHistory', JSON.stringify(history));
            localStorage.setItem('userPoints', userPoints);
            localStorage.setItem('drawCount', drawCount);
        }

        // 加载历史记录
        function loadHistory() {
            const savedHistory = localStorage.getItem('lotteryHistory');
            const savedPoints = localStorage.getItem('userPoints');
            const savedDrawCount = localStorage.getItem('drawCount');

            if (savedHistory) {
                history = JSON.parse(savedHistory);
            }

            if (savedPoints) {
                userPoints = parseInt(savedPoints);
            }

            if (savedDrawCount) {
                drawCount = parseInt(savedDrawCount);
            }
        }

        // 更新历史记录显示
        function updateHistoryDisplay() {
            historyListEl.innerHTML = '';

            if (history.length === 0) {
                historyListEl.innerHTML = '<div style="text-align: center; color: #7f8c8d; padding: 20px;">暂无抽奖记录</div>';
                return;
            }

            history.forEach(item => {
                const historyItem = document.createElement('div');
                historyItem.className = 'history-item';
                historyItem.innerHTML = `
                    <div>
                        <div class="history-prize">${item.prize}</div>
                        <div>${item.description}</div>
                    </div>
                    <div class="history-date">${item.date}</div>
                `;

                historyListEl.appendChild(historyItem);
            });
        }

        // 清空历史记录
        function clearHistory() {
            if (history.length === 0) {
                alert("暂无历史记录可清除!");
                return;
            }

            if (confirm("确定要清空所有抽奖记录吗?")) {
                history = [];
                saveHistory();
                updateHistoryDisplay();
            }
        }

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html>

功能说明

积分系统

抽奖转盘

奖品设置

历史记录

响应式设计

这个系统完全使用HTML、CSS和JavaScript实现,无需任何外部库或后端支持,可以直接在浏览器中运行。所有数据都保存在浏览器的localStorage中。

相关推荐