代码分析
1. HTML 部分
-
结构:
- 外层是一个容器
.lottery-container
,用grid
布局形成 3x3 的九宫格。 - 宫格中包含 8 个奖品格子 (
.lottery-item
) 和 1 个“开始抽奖”按钮 (.lottery-button
)。 - 每个奖品格子使用了图片和文字描述
- 外层是一个容器
-
关键节点:
- 抽奖按钮有
id="item-8"
。 - 奖品格子通过
id="item-0"
~id="item-7"
标识。
- 抽奖按钮有
2. CSS 部分
- 布局与样式:
- 使用
grid-template-columns
创建九宫格的 3x3 布局,每个格子大小为120px x 120px
,并设置了间距 (gap
)。 - 奖品格子:
- 默认样式设置了背景颜色和圆角。
- 鼠标悬停的过渡动画 (
transition
) 增加了视觉效果。
- 活跃状态 (
.active
):- 添加阴影效果,使当前抽奖格子突出显示。
- 抽奖动画:
- 使用
transform
和box-shadow
实现点击和悬停的动态效果。
- 使用
- 使用
3. JavaScript 部分
- 功能逻辑:
- 抽奖核心逻辑:
- 获取所有奖品格子(
items
),以及“开始抽奖”按钮。 - 使用
currentIndex
追踪当前高亮格子的索引位置。 - 随机生成奖品索引
prizeIndex
,表示最终中奖的奖品。
- 获取所有奖品格子(
- 点击事件监听:
- 为
item-8
按钮绑定点击事件,用来触发抽奖。 - 防止重复点击:通过检查
timer
确保只允许一次抽奖。
- 为
- 抽奖动画实现:
- 使用
setTimeout
模拟抽奖的动画效果,依次高亮九宫格中的格子。 - 动画速度控制:
- 初始速度为
100ms
(可自定义)。 - 进入最后 8 步时,速度逐渐减慢(每步增加
30ms
)。
- 初始速度为
- 抽奖结束时,显示dialog对话框显示中奖结果。
- 使用
- 抽奖核心逻辑:
4. 弹窗改进的逻辑:HTML dialog
替代 alert
Alert弹窗:
setTimeout(() => {alert(`恭喜你获得了${items[prizeIndex].innerText}奖品`);
}, 500);
Dialog对话框:
html"> <!-- Dialog 对话框 --><dialog id="resultDialog"><p id="dialogMessage"></p><button id="closeDialog">关闭</button></dialog>
const dialog = document.getElementById('resultDialog');
const dialogMessage = document.getElementById('dialogMessage');setTimeout(() => {// 往dialog内插入文本dialogMessage.innerText = `恭喜你获得了${items[prizeIndex].innerText}奖品`;dialog.showModal();}, 500);closeDialogButton.addEventListener('click', () => {dialog.close();
});
为什么改用 <dialog>
?
- 缺点:
alert
是同步阻塞的,用户体验较差,且无法自定义样式。- 弹窗样式固定,不符合设计要求。
- 优点:
<dialog>
提供更灵活的方式,允许自定义样式和布局。- 更易扩展,比如添加确认按钮或关闭按钮。
替换逻辑:
- 在 HTML 中新增
<dialog>
节点,用于展示中奖结果。 - 修改 JavaScript,使抽奖结束后更新
<dialog>
的内容,并控制其显示和关闭。
改进后关键代码片段
HTML:
html"><dialog id="result-dialog"><p id="result-text"></p><button id="close-dialog">关闭</button>
</dialog>
CSS(补充样式):
dialog {border: none;border-radius: 8px;padding: 20px;background: white;box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);text-align: center;
}
JavaScript:
javascript">const dialog = document.getElementById('result-dialog');
const resultText = document.getElementById('result-text');
const closeDialog = document.getElementById('close-dialog');// 绑定关闭按钮事件
closeDialog.addEventListener('click', () => dialog.close());function startLottery(step) {items[currentIndex].classList.remove('active');currentIndex = step % 8;items[currentIndex].classList.add('active');if (step < totalSteps) {timer = setTimeout(() => startLottery(step + 1), speed);if (step > totalSteps - 8) speed += 30;} else {clearTimeout(timer);timer = null;setTimeout(() => {resultText.textContent = `恭喜你获得了${items[prizeIndex].innerText}奖品`;dialog.showModal();}, 500);}
}
完整代码
html"><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>九宫格抽奖</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f0f0f0;}.lottery-container {display: grid;grid-template-columns: repeat(3, 120px);gap: 10px;background: #fff;padding: 20px;}.lottery-item {width: 120px;height: 120px;border-radius: 5px;display: flex;flex-direction: column;justify-content: center;align-items: center;background-color: #f9fafb;transition: all 0.3s ease;}.lottery-item img {width: 60%;height: auto;}.lottery-item span {margin-top: 5px;font-size: 14px;color: #333;}.lottery-item.active {background-color: #e5e7eb;box-shadow: 0 0 20px #333;}.lottery-button {background-color: #000000;color: white;font-weight: bold;cursor: pointer;transition: transform 0.2s, box-shadow 0.2s;}.lottery-button:hover {transform: scale(1.1);box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);}.lottery-button:active {transform: scale(0.9);}dialog {border: none;border-radius: 8px;padding: 20px;box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);background: white;font-family: Arial, sans-serif;width: 300px;text-align: center;}dialog button {margin-top: 15px;padding: 10px 20px;background-color: #007bff;color: white;border: none;border-radius: 5px;cursor: pointer;transition: background-color 0.3s;}dialog button:hover {background-color: #0056b3;}</style>
</head>
<body><div class="lottery-container"><div class="lottery-item" id="item-0"><img src="../Image/gift9/IMG (1).png" alt=""><span>智能手机</span></div><div class="lottery-item" id="item-1"><img src="../Image/gift9/IMG (2).png" alt=""><span>无线耳机</span></div><div class="lottery-item" id="item-2"><img src="../Image/gift9/IMG (3).png" alt=""><span>智能手表</span></div><div class="lottery-item" id="item-7"><img src="../Image/gift9/IMG (8).png" alt=""><span>充电宝</span></div><div class="lottery-item lottery-button" id="item-8">开始抽奖</div><div class="lottery-item" id="item-3"><img src="../Image/gift9/IMG (4).png" alt=""><span>蓝牙音箱</span></div><div class="lottery-item" id="item-6"><img src="../Image/gift9/IMG (7).png" alt=""><span>无线充电器</span></div><div class="lottery-item" id="item-5"><img src="../Image/gift9/IMG (6).png" alt=""><span>运动手表</span></div><div class="lottery-item" id="item-4"><img src="../Image/gift9/IMG (5).png" alt=""><span>无线鼠标</span></div></div><!-- Dialog 对话框 --><dialog id="resultDialog"><p id="dialogMessage"></p><button id="closeDialog">关闭</button></dialog><script>javascript">const items = document.querySelectorAll('.lottery-item:not(.lottery-button)');const dialog = document.getElementById('resultDialog');const dialogMessage = document.getElementById('dialogMessage');const closeDialogButton = document.getElementById('closeDialog');let currentIndex = 0;let prizeIndex = Math.floor(Math.random() * 8);let timer;document.getElementById('item-8').addEventListener('click', () => {if (timer) return;prizeIndex = Math.floor(Math.random() * 8);let speed = 100;let rounds = 3;let totalSteps = rounds * 8 + prizeIndex;function startLottery(step) {items[currentIndex].classList.remove('active');currentIndex = (step % 8);items[currentIndex].classList.add('active');if (step < totalSteps) {timer = setTimeout(() => startLottery(step + 1), speed);if (step > totalSteps - 8) speed += 30;} else {clearTimeout(timer);timer = null;setTimeout(() => {// 设置对话框内容并显示dialogMessage.innerText = `恭喜你获得了${items[prizeIndex].innerText}奖品`;dialog.showModal();}, 500);}}startLottery(0);});// 关闭对话框closeDialogButton.addEventListener('click', () => {dialog.close();});</script></body>
</html>