Pool Hadiah · 设计规范
视觉风格:暗金 + 品红的节日感 + 宝藏宝箱的游戏化隐喻。 设计基准:375 × 812(iPhone 标准),所有尺寸等比缩放到 vw。
色彩 Token
/* Background */
--bg-0 #1a0320 深紫底色
--bg-1 #2d0b3a 中紫
--bg-2 #4a1232 暗红紫
/* Gold (主色/点缀) */
--gold-1 #ffe9a8 高亮金
--gold-2 #ffc24b 主金
--gold-3 #e28b14 深金
--gold-4 #8a4a0a 金属投影
/* Accent (强调) */
--red #ff3f6e 粉红(任务槽位/主 CTA 辅助)
--pink #ff6fa8 浅粉
--green #4adc70 成功/+10 浮字
/* Neutral */
--ink #1a0320 按钮文字
--paper #fff7e2 卡片高亮
背景不是纯色:三层叠加,顶部玫红径向渐变 + 底部紫蓝径向渐变 + 整体紫黑线性渐变, 上面再盖一层 8% 不透明度的噪声图以避免色带,最后 conic 光芒慢速旋转。
字体
| 用途 | 字体 | 字重 | 字号 |
|---|---|---|---|
| 标题(Pool Hadiah) | Fraunces | 900 | 38px |
| Eyebrow (EVENT SPESIAL) | DM Sans | 500 | 10px tracking 4px |
| 副标题 | DM Sans | 400 | 12px |
| 奖池数字 | Bebas Neue | 400 | 44px |
| 中奖数字 | Bebas Neue | 400 | 88px |
| 按钮文字 | Fraunces | 900 | 18px tracking 4px |
| 正文 | DM Sans | 400 | 11-13px |
字号最终会被 postcss 转成 vw,在 iPhone SE 会略小,在 Plus 系列会略大。
间距规范
外边距横向 20px
卡片内边距 14-18px
卡片间距 10-14px
按钮高度 56px (主) / 42px (次)
圆角 14-16px (卡片) / 56px (主按钮) / 42px (次按钮)
组件布局(375 × 812 基准)
0 ┌──────────────────────────────┐
14 │ ‹ [Aturan ›] │ TopBar 46px
46 │ │
50 │ [EVENT SPESIAL] │
66 │ Pool Hadiah │ Title 70px
100 │ Undang Teman · Bagi Hadiah │
120 │ │
134 │ ┌ Pool Card ─────────────┐ │
│ │ Total Pool • LIVE │ │ PoolCard 108px
│ │ [🪙] 8,420 KOIN │ │
│ │ 2,817 peserta · +10 │ │
244 │ └─────────────────────────┘ │
254 │ ┌ Task Card ─────┬──────┐ │
│ │ Undang 3 Lv.2 │+10 │ │ TaskCard 82px
│ │ ⚫⚫○ 1/3 │ KOIN │ │
│ │ +10 koin/teman │Undang│ │
336 │ └────────────────┴──────┘ │
340 │ │
│ ┌ Scene ┐ │
│ │ ☀️🧰 │ │ Scene 240px
│ │ │ │
580 │ └────────┘ │
590 │ Putaran 03 : 42 : 18 │
610 │ [ BUKA SEKARANG ] │ Bottom 202px
670 │ 👥 Jihan baru dapat 12 Koin │
690 │ Hak penuh · ShortPro │
812 └──────────────────────────────┘
中奖揭晓后,.scene 里出现 Prize Reveal(绝对定位居中),
底部按钮切换为 Tarik Lagi + Undang Teman · Pool Naik 两列。
动画时间轴
常态(idle)
bg-rays 旋转一圈 40s, 循环
halo 脉冲 3s 一个呼吸
chest 上下浮动 3s 一周期 (-6px)
sparkle 16 颗,上升 6-14s,opacity 0 → 1 → 0
CTA rings 两圈交替外扩 2.2s,delay 1.1s
live msg 每 2.8s 换一条
pool +10 每 3.2-4.7s 一次,count-up 500ms
开奖中(revealing)
0 ms click → stage 切到 .revealing
按钮变 spinner
震动 [30,40,30,40,80]
chest 开始 0.15s 剧烈抖动
halo 改 0.4s 快速脉冲
scene-rays opacity 0 → 0.8, 周期从 8s 变 1.5s
1800 ms 切到 .revealed(后端结果必须这时候到齐)
揭晓(revealed)
0 ms chest 播 openBounce 0.8s(scale 1 → 1.15 → 1.05)
lid 用 0.6s cubic-bezier(.3,1.6,.5,1) 翻转 -35deg
震动 [50,30,100]
28 枚金币径向飞散 1.6s(随机 0-0.3s 延迟)
50 片彩纸下落 1.8-3.2s(随机)
prize-reveal 播 prizePop 0.8s(scale 0.3 → 1.1 → 1)
prize 数字 count-up 1000ms(easeOutCubic)
pool 数字扣除 count-up 900ms
300 ms actions 行滑入(opacity + translateY)
任务进度变化
slot fill 0.5s cubic-bezier(.3,1.5,.5,1) 弹跳出现
pool bump +10 绿色浮字 1.4s 向上飘
mission 完成 Toast 2.5s,震动 [40,20,80]
task-card 切到 .done,背景转绿
特效配置
| 元素 | 数量 | 分布 | 时长 |
|---|---|---|---|
| Sparkle | 16 | 全屏随机 x | 6-14s 循环 |
| Coin burst | 28 | 径向均分 + 抖动 | 1.6s |
| Confetti | 50 | 顶部随机 x | 1.8-3.2s |
低端机(hardwareConcurrency ≤ 4)下: - Sparkle 隐藏 - bg-rays 隐藏 - grain 隐藏 - backdrop-filter 关闭 - 粒子总数维持(视觉主 payoff 不能砍)
文案总表(印尼语)
| 位置 | 文案 |
|---|---|
| Eyebrow | EVENT SPESIAL |
| Title | Pool Hadiah |
| Subtitle | Undang Teman · Bagi Hadiah Bersama |
| Rules button | Aturan › |
| Pool label | Total Pool Hari Ini |
| Pool live dot | LIVE |
| Pool unit | KOIN |
| Pool meta left | {N} peserta |
| Pool meta right | Setiap user baru = +10 Koin |
| Task title | Undang 3 Teman ke Lv.2 |
| Task sub | Tiap teman Lv.2: Pool +10 Koin |
| Task progress | {N} / 3 |
| Task done | ✓ Misi selesai, hadiah sudah masuk |
| Reward badge | +10 KOIN |
| Invite button | Undang / Tersalin ✓ |
| Countdown | Putaran berikutnya {hh}:{mm}:{ss} |
| Main CTA | BUKA SEKARANG |
| Loading | Sedang membuka... |
| Prize label | SELAMAT! KAMU DAPAT |
| Prize unit | KOIN |
| Prize tag | Sudah masuk dompet ✦ |
| Action 1 | Tarik Lagi |
| Action 2 | Undang Teman · Pool Naik |
| Live feed | {Name} baru saja dapat {N} Koin |
| Toast invite | 🔗 Link undangan tersalin |
| Toast mission | 🎉 Misi Selesai! +10 Koin masuk dompet |
| Legal | Hak penuh event ini milik ShortPro |
按钮状态
主按钮 .draw-btn 有四种视觉状态:
| 状态 | 背景 | 文字颜色 | 投影 | 可点击 |
|---|---|---|---|---|
默认 (idle) |
金色 #ffe9a8 → #ff7a2e |
深棕 #4a1a03 |
金色深投影 + 橙色光晕 | 是 |
加载中 (is-loading) |
暗金 #c9a066 → #a87a3a |
暗棕 60% | 同默认 | 否 |
灰态 (is-disabled) |
灰蓝 #e8ecf1 → #b8bcc5 |
深紫 55% | 暗灰深投影 | 否 |
按下 (:active) |
同默认 | 同默认 | 深度 -4px,投影压扁 | — |
灰态同时触发 .draw-btn-wrap 的 .is-disabled,关闭外扩光圈动画,
避免灰按钮有金色光圈违和。
次要按钮 "Tarik Lagi" 灰态(.is-disabled-outline):
- 背景 rgba(255,255,255,.05),边框 15% 金
- 文字 35% 金
- 文案换成 "Besok 21:00"
每日 21:00 开放规则
按钮有三个阶段:
< 21:00 按钮灰态 · "DIBUKA JAM 21:00 · HH:MM:SS" · 倒计时实时刷新
≥ 21:00 且 次数 = 0 按钮灰态 · "AJAK 3 TEMAN UNTUK DAPAT TARIKAN"
≥ 21:00 且 次数 > 0 按钮金色 · "BUKA SEKARANG · Nx" · 可连抽直到次数耗尽
顶部副倒计时的文案也会联动:
locked-before-21 → "Dibuka dalam HH:MM:SS"
no-chances → "Butuh tarikan HH:MM:SS"
available → "Event aktif sekarang HH:MM:SS"(指下一个 21:00)
点到灰态按钮时弹 Toast:
- locked-before-21 →
⏰ Event dibuka jam 21:00 setiap hari - no-chances →
🎯 Ajak 3 teman untuk dapat kesempatan tarik
两阶段任务 + 抽奖次数
任务卡片按阶段切换视觉:
| 阶段 | 奖励徽章 | 徽章色 | 副文案 |
|---|---|---|---|
| Phase 1(未完成) | +10 KOIN |
金色 | "Misi 1× saja. Setelah selesai dapat kesempatan tarik." |
| Phase 2(已完成 Phase 1) | +1 TARIK |
粉红色 | "Tiap 3 teman Lv.2: +1 Tarikan" |
Phase 2 时进度条下方额外显示 · Total Nx,展示累计获得的抽奖次数。
抽奖次数 Chip:
当 drawChances > 0 且未处于 revealed 状态时,按钮上方显示一个小 chip:
● 3x Kesempatan Tarik Siap (21:00 后可用)
● 3x Siap dibuka jam 21:00 (21:00 前等待)
视觉细节:
- 胶囊圆角,金粉红渐变背景 rgba(255,196,95,.22) → rgba(255,63,110,.14)
- 左侧金色小圆点 1.2s 闪烁
- 次数用 Bebas Neue 18px,显眼
- 出现时 0.4s cubic-bezier 弹跳
按钮文案总表:
| 状态 | 主按钮 | 次要按钮 (Tarik Lagi) |
|---|---|---|
| 21:00 前 | DIBUKA JAM 21:00 · HH:MM:SS (灰) |
Ajak teman untuk tarikan (灰) |
| 21:00 后,0 次 | AJAK 3 TEMAN UNTUK DAPAT TARIKAN (灰) |
同上 |
| 21:00 后,N 次 | BUKA SEKARANG · Nx (金) |
Tarik Lagi · Nx (金) |
Grand Prize 展示
奖池卡片底部通过虚线分割,展示一行 Grand Prize:
──────────────────────────────────
● GRAND PRIZE [🪙] 4,280 untuk satu pemenang
- 左侧红色小圆点 + "GRAND PRIZE" 1.5px 字间距标签
- 中间 Bebas Neue 16px 金色数字,前面小金币图标
- 右侧 9.5px 斜体灰色提示"untuk satu pemenang di akhir event"
- 小圆点 1.2s 脉冲闪烁,和 LIVE 标签的节奏一样
数字会跟随所有用户的抽奖事件增长(每笔抽奖的 5%),具有社会证明效应。
规则弹窗(Aturan Modal)
触发:点顶部右上角 "Aturan ›" 按钮
样式:底部上滑 bottom-sheet,背景模糊 6px,最大高度 82%
6 条规则列表: 1. 邀请 3 个 Lv.2 好友得 10 Koin(一次性) 2. 之后每 3 个 Lv.2 好友 +1 抽奖机会(可重复) 3. 每天 21:00 开放抽奖 4. 抽奖金额 5-15 随机 5. 每次抽奖的 5% 入 Grand Prize,活动末抽一名幸运儿独得 6. 凡参与者都有机会中 Grand Prize
每条左侧带金色圆形编号 chip,右侧加粗关键字为金色。
底部主按钮 "Mengerti"(我知道了),点击关闭弹窗。 点遮罩区域也会关闭。
交互细节
- 触觉反馈:支持
navigator.vibrate的设备在 Draw 和 Reveal 时震动 - 防误触:Draw 过程中按钮
pointer-events: none,同时状态机锁住 - 复制链接:优先用
navigator.clipboard,降级到execCommand('copy') - Toast 重叠:同时只显示一条,后来的覆盖前面的(重启动画)
- Safe area:底部用
env(safe-area-inset-bottom)适配全面屏 - Reduced motion:
prefers-reduced-motion: reduce关闭所有循环动画
视觉 QA 检查单
过审时请确认以下点在真机上一致:
- [ ] 背景光芒在慢速旋转
- [ ] 宝箱有 3s 呼吸上下浮动
- [ ] 奖池数字每 3-4 秒 +10 并有绿色浮字
- [ ] 任务进度槽位填充有弹跳动画
- [ ] 点 BUKA SEKARANG 后先抖动 1.8s 才开奖
- [ ] 开奖后金币从中心爆开到四周,不是直线
- [ ] 彩纸是 50 片向下飘(不是向上)
- [ ] 中奖数字从 0 缓动到结果,不是直接显示
- [ ] Actions 两个按钮有 300ms 延迟后滑入
- [ ] Toast 出现和消失都有缩放
- [ ] 任务完成后 task-card 变绿,+10 badge 变绿
- [ ] iPhone 刘海/胶囊区不被顶部内容遮挡
- [ ] Home Indicator 区域(底部)不被按钮压住
- [ ] 21:00 前按钮是灰白不可点,显示倒计时文案
- [ ] 21:00 整点时按钮自动切回金色可点(无需刷新)
- [ ] 次数 = 0 时按钮是灰白 "AJAK 3 TEMAN..." 文案,即便 21:00 后
- [ ] Phase 1 完成后任务卡切换到粉红"+1 TARIK"徽章,进度重置到 0/3
- [ ] Phase 2 每完成一轮 3/3,抽奖次数 +1,任务重置继续
- [ ] 抽奖次数 > 0 时按钮上方出现金粉渐变 chip 显示 "Nx 次数"
- [ ] 每次抽奖消耗 1 次,次数减 1,可连抽直到耗尽
- [ ] 刷新页面后任务进度和抽奖次数保持(localStorage 兜底)
- [ ] 用
?state=locked|available|no-chancesURL 参数可预览三种按钮状态