核心逻辑是用globalcompositeoperation="destination-out"在纯色不透明遮罩层上“挖除”像素,露出底层奖品内容;需适配高dpr、阻止触摸默认行为,并通过区域累加或getimagedata量化刮开面积判定完成。

刮刮卡用 canvas 实现的核心逻辑是什么
刮刮卡效果本质是「局部擦除遮罩层」,不是真的“刮开”内容,而是用 canvas 的 globalCompositeOperation = 'destination-out' 模式,在不透明图层上“挖掉”一块区域,露出底层文字或图片。关键点在于:遮罩层必须是纯色(通常是灰色或黑色),且 fillStyle 不透明度要设为 1;底层内容(如“谢谢参与”)需提前绘制在 canvas 底部或作为背景图叠放。
touchstart/touchmove 在移动端刮不动?
移动端默认会触发滚动或缩放,导致 touchmove 被拦截或坐标偏移。必须显式阻止默认行为,并用 preventDefault() —— 但只对目标 canvas 元素生效,不能写在 document 上:
canvas.addEventListener('touchstart', e => {
e.preventDefault();
isDrawing = true;
});
canvas.addEventListener('touchmove', e => {
e.preventDefault(); // 关键:否则手指一滑就页面滚动了
const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
const x = touch.clientX - rect.left;
const y = touch.clientY - rect.top;
ctx.lineTo(x, y);
ctx.stroke();
});<h3>刮开面积判断用 <code>ctx.getImageData()</code> 还是计数像素?</h3><p>用 <code>getImageData</code> 获取整个遮罩区域的像素数据再遍历,性能差、卡顿明显,尤其在低端安卓机上。更实用的做法是:记录每次笔画覆盖的矩形区域(<code>strokeRect</code> 或缓存路径 bounding box),累加面积后与阈值(如总遮罩面积的 60%)比较。注意:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8714" title="HTML汇报生成器"><img
src="https://img.php.cn/upload/skill/000/000/081/179220974213190.jpg" alt="HTML汇报生成器" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8714" title="HTML汇报生成器" class="overflowclass">HTML汇报生成器</a>
<p class="overflowclass">🚀 不用写一行代码!把项目总结、工作汇报、研究报告、技术文档、提案、数据看板直接变精美HTML。12种主题 × 11种背景动效 × 9种鼠标特效 × 10种边框样式 × 实时调色器 × 毛玻璃卡片 × PDF导出,生成后还能自由调色,零门槛AI直出。触发词:项目总结、工作汇报、PPT、生成报告、做个总结、HTML文档、数据报告、流程文档、会议纪要、技术文档、研究报告、数据看板、提案、做个展示页、帮我做个汇报、文档生成。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8714" title="HTML汇报生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 不要每帧都调用
getImageData,它触发 GPU 同步,代价高 - 用
ctx.isPointInPath(x, y)判断单点是否在已刮区域,适合做“是否已刮开”的轻量判断 - 若需精确识别“刮开图案”,建议预先用 SVG 或 CSS mask 做静态遮罩,canvas 只负责响应交互
IE 或旧版 Safari 不支持 destination-out 怎么办
IE11 及更早版本不支持该合成模式,Safari 12 之前也有兼容问题。替代方案是用两层 canvas:上层画半透灰(rgba(128,128,128,0.8)),下层放奖品文字;刮的时候用 clearRect 清空上层对应区域。虽然效果略“毛边”,但稳定可靠:
// 上层 canvas(遮罩层) topCtx.clearRect(x - 10, y - 10, 20, 20); // 刮一个圆点,实际用 path 更顺滑 // 下层 canvas(奖品层)保持不变,自然透出
真正难的不是画出刮刮卡,而是让不同设备上的手指轨迹平滑、响应及时、刮开判定不误判——这些细节藏在事件节流、坐标归一化和 canvas 像素比适配里,容易被当成“样式问题”忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










