九宫格抽奖需用grid布局+类名切换实现高亮/放大效果,而非rotate旋转;应采用伪随机滚动加真随机落点算法,并处理移动端事件、本地存储等细节。

九宫格抽奖不是转盘,别用 rotate 硬套
很多人一看到“抽奖动画”就下意识往 CSS transform: rotate() 上靠,结果做出来是转盘,不是九宫格。九宫格本质是 3×3 网格中某个格子高亮/放大/闪动,再配合顺序点亮或随机跳转的视觉节奏——它不依赖中心旋转,而是靠 grid 布局 + animation 或 JS 控制类名切换。
常见错误现象:rotate(360deg) 转一整页、格子跟着歪、点击后位置错乱、无法精准停在目标格。
- 用
display: grid定义容器,设grid-template-columns: repeat(3, 1fr) - 每个奖品格用独立
<div>,加统一 class 如cell,中奖格额外加active - 动画用
@keyframes pulse或scale(1.2) box-shadow,避免影响布局流
Math.random() 直接选格会假随机,要加防连抽逻辑
纯靠 Math.random() * 9 | 0 生成 0–8 下标,连续抽奖时容易重复或集中某几格,用户一眼看出“不真”。真实抽奖需模拟物理停顿感:先快速滚动(伪随机),再减速落点(真随机锁定)。
使用场景:按钮点击触发,需支持暂停/重置;多人同时抽奖时不能共享同一随机种子。
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 用
let current = 0记录当前高亮格索引,定时器每 100ms 更新一次 - 前 15 次用
(current + Math.floor(Math.random() * 3) + 1) % 9跳跃,制造混乱感 - 最后 3–5 次改用预设路径数组,比如
[2, 5, 8, 7, 6],确保终点可控 - 中奖格确定后,清空定时器,再执行一次
classList.add('winner')
移动端点击失效?检查 touchstart 和 preventDefault
PC 端点按钮好好的,手机上要点两下才触发,甚至完全无响应——大概率是事件绑定用了 click,但 iOS Safari 对快速点击有 300ms 延迟,且某些 CSS 触发了默认行为拦截。
性能影响:加 touchstart 后若不做节流,快速连点可能启动多轮抽奖。
- 按钮监听
touchstart和click双事件,用event.preventDefault()阻止默认行为 - 加状态锁:
if (isRunning) return,抽奖开始后禁用按钮,结束后恢复 - 避免给
cell格子本身绑touchstart,只操作控制按钮,否则格子间缝隙会导致误失焦
中奖数据没存本地?localStorage 存的是字符串,别直接塞对象
想记录“张三抽中 iPad”,刷新页面就没了。有人直接 localStorage.setItem('history', historyArray),结果存进去是 toString() 后的逗号分隔字符串,取出来根本没法遍历。
兼容性影响:IE8+ 支持 localStorage,但不支持 JSON.stringify 的部分特性(如 undefined 自动丢弃),需兼容处理。
- 存之前必须
JSON.stringify(historyArray),取出来立刻JSON.parse() - 加 try/catch,防止历史数据损坏导致整个页面报错:
try { ... } catch(e) { historyArray = [] } - 单条记录建议含字段:
{ name: '张三', prize: 'iPad', time: Date.now() },方便后续按时间倒序展示
九宫格抽奖真正的复杂点不在动画,而在“停在哪”和“怎么让人信”。随机算法藏在哪、中奖是否可复现、历史是否可查——这些细节比转几圈更决定用户愿不愿意再点一次。

















