Canvas刮刮卡效果核心是用globalCompositeOperation="destination-out"擦除遮盖层,通过双Canvas分层、事件追踪划线、像素检测刮开面积并优化移动端适配实现。

Canvas 实现刮刮卡效果,核心是利用 globalCompositeOperation 的 "destination-out" 模式——它能让新绘制的内容“擦除”已有内容,而不是覆盖。配合鼠标/触摸事件追踪划动路径,就能模拟刮开涂层的效果。
1. 初始化画布与图层结构
刮刮卡通常有三层:底层(中奖图案/文字)、中间层(遮盖涂层,比如灰色渐变或纹理)、顶层(用户刮擦的透明通道)。Canvas 本身不支持多图层,所以要用两个 Canvas 或一个 Canvas + 离屏 Canvas 来分离绘制:
- 主 Canvas 显示最终效果,初始只画底层(如“恭喜中奖!”)
- 用一个离屏 Canvas(
offscreenCtx)预先画好遮盖层(比如 #cccccc 纯色或带噪点的纹理),作为“刮涂层”的源 - 主 Canvas 的绘图上下文设置
ctx.globalCompositeOperation = "destination-out",这样后续绘制就变成“擦除”而非上色
2. 绑定并处理刮擦动作
监听 mousedown / touchstart、mousemove / touchmove、mouseup / touchend 事件,关键点在于平滑划线和性能优化:
- 按下时记录起点,开启绘制状态;移动时用
lineTo()连续绘线,避免点状断开 - 启用抗锯齿:
ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.lineWidth = 20;让刮痕更自然 - 触摸设备需用
event.touches[0]取坐标,并调用event.preventDefault()防止页面滚动干扰 - 可加节流(如 16ms 一帧)避免高频绘制拖慢动画
3. 刮开区域判定与交互反馈
纯视觉刮擦还不够,常需判断是否刮开足够面积来触发结果(如显示中奖信息)。可用以下轻量方法:
立即学习“Java免费学习笔记(深入)”;
- 用
ctx.getImageData(0, 0, width, height)获取像素数据,统计 alpha 值接近 0 的像素占比(即被刮开的透明区域) - 更高效的做法:维护一个布尔数组或 Uint8ClampedArray 标记“已刮区域”,每次绘制时更新对应坐标范围
- 达到阈值(如 30%)后停止响应刮擦,显示结果层(用 DOM 覆盖或 Canvas 重绘),并禁用事件监听
4. 兼容性与细节优化
移动端适配和体验细节容易被忽略,但直接影响完成率:
- 高 DPR 设备(如 iPhone)需按
window.devicePixelRatio缩放 canvas 尺寸和 lineWidth,否则刮痕过细 - 遮盖层建议用带轻微噪点的灰色(
createPattern或 canvas 绘制噪点纹理),比纯色更像真实刮刮卡 - 为提升响应感,可添加
cursor: url(brush.cur), auto自定义光标,或刮擦时播放轻微音效(AudioContext 或new Audio().play())
不复杂但容易忽略:务必在刮擦前调用 ctx.beginPath(),每次抬起后调用 ctx.closePath() 和 ctx.stroke(),否则线条可能意外连接或渲染异常。


















