Canvas刮刮乐通过双层结构实现:底层显示奖品,上层用"destination-out"模式擦除不透明涂层暴露内容;需统一处理鼠标/触摸事件、精确坐标转换、平滑路径绘制,并量化刮开面积触发结果。

Canvas实现刮刮乐效果,核心是利用globalCompositeOperation的"destination-out"模式,在覆盖层上“擦除”图像,露出底层奖品内容。关键不在画图本身,而在精确响应触摸/鼠标事件、适配不同设备、控制刮擦区域平滑度和性能。
准备双层Canvas结构
刮刮乐视觉上由两层组成:底层显示文字或图片(如“谢谢参与”“一等奖”),上层覆盖不透明涂层(如灰色渐变或纯色)。用户刮擦时,实际操作的是上层Canvas,通过像素级擦除暴露下层内容。
- 创建两个
<canvas></canvas>元素,尺寸完全一致,用CSS叠放(position: absolute+top/left: 0) - 底层Canvas绘制奖品信息(支持文字、图片、SVG转图像)
- 上层Canvas用
fillRect()铺满纯色(如#cccccc),或用createLinearGradient()绘制质感涂层
绑定并标准化刮擦事件
需同时兼容鼠标(PC)和触摸(手机),统一处理为“点序列”,避免mousemove过频或touchmove默认行为干扰。
- 监听
mousedown+touchstart启动刮擦,设isDrawing = true - 在
mousemove/touchmove中调用preventDefault()(移动端必需),并用getBoundingClientRect()将屏幕坐标转为Canvas坐标 - 记录连续点位,用
lineTo()连接形成路径,比单点arc()更顺滑 - 松开(
mouseup/touchend)后设isDrawing = false
用destination-out擦除涂层
这是实现“刮开”效果的技术核心:让新绘制的内容“挖空”已有像素,而非覆盖。
立即学习“前端免费学习笔记(深入)”;
- 对上层Canvas的2D上下文,设置
ctx.globalCompositeOperation = "destination-out" - 擦除笔触推荐用圆形(
arc())或带阴影的圆角矩形(模拟手指/鼠标粗细),半径建议15–30px - 每次绘制前设
ctx.lineWidth = 0(避免描边干扰),仅用fill()填充透明区域 - 注意:该模式对透明度敏感,涂层必须是不透明色(alpha=1),否则擦除不干净
判断刮开面积并触发结果
不能只靠视觉判断,需量化已刮区域占比,防止误判或作弊。
- 用
ctx.getImageData(0, 0, width, height)读取上层Canvas像素数据 - 遍历
data数组,统计非透明像素(data[i+3] > 0)数量,计算剩余涂层比例 - 设定阈值(如
20%),低于该值即视为“刮开”,执行回调(弹窗、跳转、播放音效) - 为防频繁检测,可用
requestAnimationFrame节流,每200ms检查一次
整个过程不依赖第三方库,原生Canvas API即可完成。重点在于事件坐标的准确映射、复合操作模式的理解,以及刮开判定的合理阈值设计。做好这四步,刮刮乐交互就稳了。



















