用HTML+JS实现H5集卡需统一data-card-id标识卡片,通过transform:rotateY+transition做翻转动画,用opacity+pointer-events禁用未获得卡;localStorage存已收集卡数组(容错解析),保底逻辑前端可模拟但需防篡改。
纯前端实现 H5 集卡,核心是「状态管理 + 视觉反馈」,不需要后端也能跑通逻辑。关键不是堆动画,而是让每张卡的状态(是否拥有、是否已翻开、是否可点击)在 DOM 和 JS 中严格同步。
常见错误:click 事件绑在图片上却没阻止冒泡,导致连点两次触发重复逻辑;或者用 display: none 隐藏未获得卡,但用户抓包就能看到所有卡名和路径。
data-card-id 统一标识卡,不要靠文件名或顺序推断transform: rotateY(180deg) + transition,别用 visibility: hidden 切换——否则无法做翻转中止或暂停opacity: 0.4 + pointer-events: none 禁用交互,而不是删掉 DOM 或隐藏<div class="card" data-card-id="tiger"> <div class="card-front"><img src="card_tiger_front.png"></div> <div class="card-back"><img src="card_tiger_back.png"></div></div>
localStorage 是 H5 集卡最轻量可靠的本地存储方案,但要注意它只存字符串,且同源限制严格——微信内嵌浏览器、QQ 浏览器、iOS Safari 的私有模式都可能禁用或清空它。
典型坑:JSON.parse(localStorage.getItem('collected')) 报 SyntaxError,因为值被意外写成了 null 或 undefined 字符串。
立即学习“前端免费学习笔记(深入)”;
const collected = JSON.parse(localStorage.getItem('collected') || '[]');
JSON.stringify(),别直接赋值对象——否则下次读出来是 [object Object]
localStorage.setItem
localStorage 不行前端生成随机卡本质是伪随机,真正的概率控制和保底(比如抽 10 次必得稀有卡)必须由后端下发结果,否则用户改 JS 就能无限刷 SSR。
但 MVP 阶段可先用前端模拟保底逻辑,仅用于演示或内测:用一个计数器记录连续未中次数,达到阈值就强制返回指定卡 ID。
localStorage 中,键名建议带时间戳前缀,比如 draw_streak_202406,避免跨月失效['common', 'common', 'rare'],要用加权随机:function weightedRandom(items) { const total = items.reduce((sum, i) => sum + i.weight, 0); let rand = Math.random() * total; for (const item of items) { rand -= item.weight; if (rand <= 0) return item.id; }}
fetch('/api/draw') 必须返回完整卡信息(含 ID、名称、稀有度、是否新卡),前端只负责渲染微信不支持运行时截图分享,document.querySelector('canvas').toDataURL() 生成的 base64 图在 onShareAppMessage 里无效——它要求的是静态资源 URL,且必须是 HTTPS、小于 5MB、域名已配置 JSAPI 安全域名。
真正能生效的方式只有一种:服务端生成分享图(含用户昵称、已收集数量、卡面缩略图拼接),返回一个固定 URL。
title 别写死,应动态拼接,例如:`${nickName} 已集齐 5 张福卡!`,从 localStorage 或接口取数据weixin://dl/setting/ 清除缓存,否则旧的 shareImage URL 会一直生效实际最难的部分不是翻转动画或抽卡逻辑,而是把「用户当前状态」在页面加载瞬间准确还原出来——包括哪几张卡已点亮、抽卡次数、保底计数、是否已完成整套。这些状态一旦错位,整个活动体验就崩了。