【DEMO】HTML+JS实现九宫格抽奖界面

代码分析

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):
      • 添加阴影效果,使当前抽奖格子突出显示。
    • 抽奖动画:
      • 使用 transformbox-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> 提供更灵活的方式,允许自定义样式和布局。
    • 更易扩展,比如添加确认按钮或关闭按钮。
替换逻辑:
  1. 在 HTML 中新增 <dialog> 节点,用于展示中奖结果。
  2. 修改 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>

效果展示:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值