代码分析
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对话框:
<!-- 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:
<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:
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);
}
}
完整代码
<!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>
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>