聚会破冰利器:一个页面装下六种派对互动工具,打开即用,结果一键分享。 适合朋友聚会、团建、直播互动,强烈建议用手机打开。
派对神器工具箱是一个零依赖、单文件、自包含的互动网页(index.html,约 76 KB)。所有视觉、动效、音效、彩带均由原生 HTML/CSS/JS 手写实现,不依赖任何第三方库、框架或构建工具。
核心设计目标
| 目标 | 实现方式 |
|---|---|
| 打开即用 | 单文件,双击即开;也能放到任意静态服务器上 |
| 聚会场景 | 移动端优先,大按钮大字号,单手可操作 |
| 结果可传播 | Web Share API 一键分享到微信/QQ 等,桌面端自动降级为剪贴板 |
| 派对氛围 | 高饱和多巴胺配色、毛玻璃卡片、夸张回弹动效、WebAudio 合成音效 |
| 工具 | 玩法 | 技术亮点 |
|---|---|---|
| 🎡 幸运转盘 | 自定义选项,拖拽甩动或自动旋转 | Canvas 绘制 3D 倾斜转盘 + 物理惯性 + 咔哒音 |
| 🎲 摇骰子 | 1–6 颗骰子,比大小定输赢 | 纯 CSS 3D 拟物骰子,翻滚弹跳定格,支持真机摇一摇 |
| 💬 真心话大冒险 | 三档尺度 × 真心话/大冒险抽卡 | 3D 翻牌动画 + 最近 5 条历史记录 |
| 🕵️ 谁是卧底 | 生成词对并发牌,传手机看词 | 22 组内置词对 + 自定义词对,4–12 人 / 1–2 卧底 |
| 🎁 抓阄抽奖 | 抽一个 / 排顺序 / 分 N 组 / 两两配对 | 滚屏揭晓 + 彩带,配对模式覆盖"随机匹配"需求 |
| 💣 倒计时炸弹 | 传炸弹看谁手忙脚乱 | 点按传递随机 +1~5 秒,最后 10 秒心跳加速,归零爆炸 |
双击 index.html,默认浏览器即打开。
# 在项目目录下任选其一
python -m http.server 8899 --directory .
# 或
npx serve -l 8899- 电脑访问:http://127.0.0.1:8899/index.html
- 手机访问(同一 Wi-Fi):
http://<电脑局域网IP>:8899/index.html,用ipconfig/ifconfig查电脑局域网 IP
为什么推荐服务方式:Web Share API 在
http:///https://下可用性最好;file://协议下分享按钮会走"复制到剪贴板 → 提示粘贴"的降级路径,功能不受影响。
- 现代移动浏览器:iOS 15+ Safari / Android Chrome 100+
- 桌面:Chrome / Edge 最新版
- 需要联网加载 Google Fonts(被墙或离线时自动回退系统字体,不影响功能)
- 点「编辑选项」修改内容:每行一个选项(逗号/顿号分隔也支持),或一键套用 3 套预设(默认惩罚 / 酒桌版 / 今晚吃什么)。
- 拖拽甩动:按住转盘快速甩出,松手后按惯性减速,自动对齐停在某个扇区;或者点「自动旋转」。
- 停稳后弹出结果,可「再转一次」或「分享结果」。
- 选项少于 2 个时禁止旋转并提示。
- 用 +/− 调整骰子数量(1–6 颗)。
- 点「开摇!」,骰子 3D 翻滚约 1.3 秒后定格,显示各骰点数与总和。
- 全部同点数触发"豹子"彩蛋(全 6 为"豹子通杀")。
- 点「摇一摇」授权后,真机物理摇动也能投骰子(iOS 需要手动授权)。
- 选择模式(真心话 / 大冒险)与尺度(轻度 / 火辣 / 高能)。
- 点「抽一张」或点击卡面,翻牌显示题目;最近 5 条自动记入历史。
- 「分享题目」可把当前题目发到聊天群。
- 设置玩家人数(4–12)与卧底人数(1–2 人,2 卧底需 ≥6 人);可选填自定义词对,不填则从 22 组内置词对随机抽取。
- 点「生成词对并发牌」,系统随机分配:平民拿词 A,卧底拿词 B。
- 传手机看词:第 N 位查看 → 点「查看我的词」→ 记住后点「我看好了 · 下一位」,依次传递。
- 全部看完后「揭晓身份」,显示平民词/卧底词及各自人数。
-
填入名单(每行一个名字),选择模式:
模式 说明 抽一个 名单滚屏 1.2 秒后揭晓中奖者 + 彩带 排顺序 洗牌输出带序号的顺序列表 分 N 组 2–10 组,轮转分配尽量均匀 两两配对 随机 CP;奇数人自动产生"自由人" -
所有模式结果均可一键分享。
- 选择时长:30/60/90 秒或自定义(10–180 秒,步进 5)。
- 点「点燃引线!」开始倒计时,手机在玩家间传递;拿到的人点「传给下一位」,每次传递随机 +1~5 秒。
- 最后 10 秒炸弹变红、心跳脉冲加速;归零时整页震动爆炸——炸到谁,谁表演。
| 角色 | 色值 | 用途 |
|---|---|---|
| 亮橙 | #FF7A1A |
主按钮、转盘扇面 |
| 玫红 | #FF2E7E |
次按钮、强调、轮毂 |
| 明黄 | #FFD60A |
结果大字、高亮 chip |
| 青蓝 | #23D5FF |
焦点环、点缀扇面 |
| 深紫渐变 | #2B0A4E → #4A0E63 → #6B1370 |
页面背景(让霓虹色跳出来) |
| 深墨 | #2A1038 |
亮色块上的文字 |
- 标题/按钮/结果大字:站酷快乐体 ZCOOL KuaiLe(派对感、覆盖简体中文)
- 数字(骰子点数、倒计时、名次):Baloo 2(圆胖拉丁数字)
- 正文:系统黑体栈(PingFang SC / MiSans / Microsoft YaHei)
全部经 Google Fonts CDN 引入并
display=swap,加载失败时回退系统圆体,功能不受影响。
- 全局弹性缓动:
cubic-bezier(.34, 1.56, .64, 1)(夸张回弹) - 页面/卡片入场:上移 + 缩放 pop-in;按钮按压:下沉 + 缩放
- 彩带:约 110 粒四色 canvas 粒子,重力 + 旋转 + 渐隐,约 1.8 秒自毁
prefers-reduced-motion下关闭漂浮 blob、彩带、抖动等装饰动画,保留全部功能
3D 倾斜 canvas 转盘:透视压缩(椭圆 squash 0.44)+ 侧面厚度 + 拖拽甩动物理 + 扇区咔哒音 + 停稳彩带爆发。其余工具保持安静精致,不抢戏。
index.html
├── <style> 设计令牌 + 全部样式(~600 行)
│ ├── CSS 变量令牌(颜色/字体/缓动/玻璃)
│ ├── 玻璃卡片 / 按钮 / chip / stepper 组件类
│ └── 各工具专属样式 + 响应式 + reduced-motion
└── <script> 原生 JS(~1000 行)
├── 通用工具:$ / shuffle / clamp / normAngle / escapeHTML
├── AudioFx WebAudio 合成音效引擎(无音频文件)
├── Confetti 彩带粒子系统
├── shareResult Web Share + 剪贴板降级
├── toast / showView 提示与视图路由
├── Wheel / Dice / Truth / Undercover / Lottery / Bomb 六个工具模块
└── init 模块注册、静音开关、音频解锁、导航绑定
转盘物理(Wheel)
- 指针角度差驱动旋转;松手后角速度按
0.972^帧摩擦衰减 - 拖拽中的角速度用指数移动平均平滑(
v = .8v + .2·(Δθ/Δt)) - 减速到阈值后,用 easeOutBack 弹性动画把最近扇区吸附到指针中心
- 扇区边界划过指针时触发
tick()咔哒音 + 指针弹跳 - Canvas 用
scale(1, 0.44)实现椭圆透视,深色底座椭圆模拟侧面厚度
3D 骰子(Dice)
- 六面用 CSS 3D 变换定位(标准立方体面变换 +
translateZ) - 目标点数的方位映射
ROT(如 3 点 =rotateX(90°) rotateY(-90°),经法向量代数推导) - 翻滚:随机起始姿态 → 强制回流 → 目标姿态追加 1–2 个 360° 整圈,交给 CSS transition 插值,回弹曲线定格
- 真机摇一摇:DeviceMotion 加速度阈值 23,iOS 13+ 需
requestPermission()(按钮手势内发起)
分享降级链(shareResult)
navigator.share({text}) // 移动端 → 系统分享面板(微信/QQ…)
├─ 用户取消(AbortError) → 静默返回
└─ 失败/不可用
→ navigator.clipboard.writeText // 复制成功 → toast「已复制」
└─ 失败 → toast 直接展示待分享文本
音效合成(AudioFx)
- 全部由振荡器 + 白噪声经 Gain 包络实时合成:pop / tick / whoosh / rattle / boom / fanfare
- AudioContext 在首次手势时解锁(iOS 要求);静音状态持久化到 localStorage
视图路由(showView)
- 无框架单页切换:
.view.active控制显隐,每个模块暴露enter()/leave()钩子(如炸弹离开即重置计时) - 无障碍:切换时把残留在旧视图的焦点 blur,并
tabindex="-1"聚焦新视图容器(标准 SPA 焦点迁移模式),键盘 Tab 从视图内首个元素继续
- 真心话/大冒险:3 档 ×(12 真心话 + 12 大冒险)= 72 条原创题目
- 谁是卧底:22 组词对(包子/饺子、王者荣耀/英雄联盟……)
- 转盘预设:默认惩罚 / 酒桌版 / 今晚吃什么
本项目的实际开发路径(含踩坑记录):
- 需求分析 → 关键词(幸运转盘/真心话大冒险/倒计时炸弹/随机匹配)与核心交互(轮盘/骰子/卧底/抓阄)合并为六个工具,保证每个需求词都有落点。
- 设计先行 → 先定设计令牌(配色/字体/缓动/签名元素),通过 frontend-design 流程评审后才写代码;签名元素只设一个(3D 转盘),其余克制。
- 分块实现 → HTML+CSS 骨架 → 核心 JS(工具层 + 转盘)→ 其余五工具 → 初始化绑定;每块独立写入,
node --check做语法校验。 - 自动化验证 → Playwright 全量交互回归(23 项)+ 程序化视觉断言(12 项),全部通过、零 JS 报错。
- 修复过程中发现的真实缺陷:
- 拖拽打断转盘吸附动画时
requestAnimationFrame句柄冲突 → 拖拽开始先取消未决帧 - 隐藏视图下 canvas 尺寸读取为 0 → resize 加显隐守卫
- 切换视图后焦点残留在隐藏按钮上,Chromium 键盘焦点链卡死 → 视图切换时迁移焦点(SPA 标准做法)
- 分享降级:
file://非安全上下文无剪贴板 API → 增加"toast 直接展示文本"兜底
- 拖拽打断转盘吸附动画时
| 场景 | 行为 |
|---|---|
| 转盘选项 < 2 | 禁止旋转/拖拽,toast 提示「先加两个以上选项再转」 |
| 转盘选项很多(>10) | 扇面字号自适应缩小(19→11px),超长文本截断 |
桌面浏览器无 navigator.share |
剪贴板复制;剪贴板也不可用时 toast 展示待分享文本 |
| 用户取消系统分享面板 | 静默返回,不打扰 |
| iOS 音频 | 首次手势解锁 AudioContext;静音状态持久化 |
| 卧底人数非法 | 2 卧底需 ≥6 人,chip 自动禁用并回退 1 人;人数硬限 4–12 |
| 配对奇数人 | 自动产生「自由人」;单人名单提示「再拉个朋友」 |
| 炸弹切后台/锁屏 | 计时基于时间戳差值,不漂移;离开工具页即重置 |
| 转盘结果弹窗 | 点遮罩或 Esc 关闭;aria-modal + aria-labelledby 标注 |
| 减少动态效果偏好 | 关闭装饰动画,保留全部功能 |
- 交互回归:23 项 Playwright 用例全部通过 —— 转盘拖拽甩动停稳出结果、自动旋转、自定义选项、骰子 1–6 颗滚动求和、三档抽卡与历史、卧底 6 人发牌→传看→揭晓(词对分布校验如
狗×5 / 猫×1)、抽奖四模式(含奇数自由人)、炸弹真实归零爆炸、重进重置。 - 程序化视觉断言:12 项全部通过 —— 移动端/桌面端零横向溢出、两套字体加载、毛玻璃
backdrop-filter生效、转盘画布四色调色板采样命中、骰子六面变换互异、结果弹窗在视口内、键盘焦点环可见。 - 质量门槛:全程零
console.error/pageerror。
复跑测试(验证依赖已从工作区移除,需要时重装):
pip install playwright # 安装 Python 包
python -m playwright install chromium # 下载浏览器
# 设置环境变量后运行脚本
PYTHONPATH=... PLAYWRIGHT_BROWSERS_PATH=... python _screenshots/test_party.py
PYTHONPATH=... PLAYWRIGHT_BROWSERS_PATH=... python _screenshots/test_visual.py截图留存于 _screenshots/*.png(首页/各工具/结果态/桌面端共 16 张)。
- Google Fonts 需联网:站酷快乐体与 Baloo 2 走 CDN;被墙/离线时回退系统字体,布局与功能不受影响。如需完全离线,可下载 woff2 内联为 base64。
file://非安全上下文:剪贴板 API 不可用,分享走 toast 兜底;建议用本地服务方式运行。- 摇一摇:仅真机有效,iOS 需在「摇一摇」按钮手势内完成权限请求;桌面浏览器静默降级为按钮摇。
- 毛玻璃效果:依赖
backdrop-filter,极老浏览器会退化为半透明卡片(不影响使用)。 - 多人同时操作:页面为单机单页设计,无后端同步;聚会场景建议一个设备投屏或传递使用。
project3/
├── index.html # 唯一交付物:完整应用(样式+脚本内联,76.4 KB)
└── README.md # 本文档
- 词库/题库存 localStorage 自定义与导入导出
- 转盘扇面权重设置、动画音效开关
- 谁是卧底增加"投票出局"记分环节
- 抽奖名单本地持久化(常用名单免重复输入)
- PWA 化(离线缓存 + 添加到主屏幕)
- 多端同步(WebSocket 房间模式,直播互动场景)
文档基于项目实际构建与测试记录整理;版本随 index.html 同步演进。