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

embedded/2024/12/21 14:51:10/

代码分析

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对话框

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

效果展示:

在这里插入图片描述


http://www.ppmy.cn/embedded/147552.html

相关文章

面试题整理4----lvs,nginx,haproxy区别和使用场景

LVS、Nginx、HAProxy&#xff1a;区别与使用场景 1. LVS&#xff08;Linux Virtual Server&#xff09;1.1 介绍1.2 特点1.3 使用场景 2. Nginx2.1 介绍2.2 特点2.3 使用场景 3. HAProxy3.1 介绍3.2 特点3.3 使用场景 4. 总结对比 在构建高可用、高性能的网络服务时&#xff0c…

只需3步,使用Stable Diffusion无限生成AI数字人视频

效果演示 先看效果&#xff0c;感兴趣的可以继续读下去。 没有找到可以上传视频的地方&#xff0c;大家打开这个链接可以看到&#xff1a;www.aliyundrive.com/s/CRBm5NL3x… 基本方法 搞一张照片&#xff0c;搞一段语音&#xff0c;合成照片和语音&#xff0c;同时让照片中…

leetcode 3285 找到稳定山的下标

3285. 找到稳定山的下标 已解答 简单 相关标签 相关企业 有 n 座山排成一列&#xff0c;每座山都有一个高度。给你一个整数数组 height &#xff0c;其中 height[i] 表示第 i 座山的高度&#xff0c;再给你一个整数 threshold 。 对于下标不为 0 的一座山&#xff0c;如果…

Redisson实现分布式锁

Redisson 是一个在Redis的基础上实现的Java驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。它不仅提供了一系列的分布式的Java常用对象&#xff0c;还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque…

在线免费公共DNS解析服务器列表

在线免费公共DNS解析服务器列表&#xff1a;推荐阿里DNS、百度DNS、Google免费DNS地址、OpenDNS地址库、114 DNS、DNSPod等 公共DNS各地区公共DNS各地电信DNS各地联通DNS各地移动DNS各地铁通DNS教育网DNS美国DNS如果配置了不合理的 DNS 服务器&#xff0c;可能会导致网速缓慢、…

虚拟现实辅助工程技术在航空领域的应用

虚拟现实辅助工程技术应用于航空领域是当前和未来的重要发展趋势。虚拟现实辅助工程技术通过虚拟环境模拟航空结构在不同工作状态下的行为和性能演化&#xff0c;为结构的优化设计、高效率制造和低成本维护提供了全方位支持。 虚拟现实辅助工程技术在航空领域的应用 1.飞机结构…

OpenCV基本图像处理操作(三)——图像轮廓

轮廓 cv2.findContours(img,mode,method) mode:轮廓检索模式 RETR_EXTERNAL &#xff1a;只检索最外面的轮廓&#xff1b;RETR_LIST&#xff1a;检索所有的轮廓&#xff0c;并将其保存到一条链表当中&#xff1b;RETR_CCOMP&#xff1a;检索所有的轮廓&#xff0c;并将他们组…

Restaurants WebAPI(一)—— clean architecture

文章目录 项目地址一、Restaurants.Domain 核心业务层1.1 Entities实体层1.2 Repositories 数据操作EF的接口二、Restaurants.Infrastructure 基础设施层2.1 Persistence 数据EF CORE配置2.2 Repositories 数据查询实现2.3 Extensions 服务注册三、Restaurants.Application用例…