Canvas刮刮卡效果通过双层Canvas实现,上层用globalCompositeOperation='destination-out'擦除遮罩,底层显示中奖内容,结合事件节流与像素采样判断刮开面积触发反馈。

在HTML5中用Canvas实现刮刮卡效果,核心是利用Canvas的像素级绘图能力与事件交互结合,通过擦除遮罩层来“刮开”隐藏的中奖信息。关键不在于复杂算法,而在于对Canvas绘图状态、合成模式(globalCompositeOperation)和鼠标/触摸事件的合理控制。
准备双层Canvas结构
刮刮卡本质是“遮罩+内容”的叠加关系。推荐用两个叠放的Canvas:底层显示中奖文字或图案,上层绘制不透明遮罩(如灰色或黑色)。用户刮擦的是上层,露出底层内容。
- 用CSS将两个Canvas绝对定位重叠,尺寸一致,父容器设
position: relative - 底层Canvas只绘制一次中奖结果(例如“一等奖:iPhone15”),无需清空
- 上层Canvas初始化时用
fillRect()铺满纯色遮罩(如ctx.fillStyle = '#ccc')
监听并响应刮擦动作
刮擦依赖连续的鼠标移动或触摸拖动事件。需记录起始点,并在移动过程中不断绘制“擦除路径”。Canvas本身不支持“橡皮擦”,但可通过globalCompositeOperation = 'destination-out'实现“擦除”效果。
- 给上层Canvas绑定
mousedown+mousemove+mouseup(桌面)或touchstart+touchmove+touchend(移动端) - 在
mousemove/touchmove中,先设置ctx.globalCompositeOperation = 'destination-out' - 再用
beginPath()→lineTo()→stroke()画出连续线条(线宽建议15–30px,模拟手指/鼠标粗细) - 注意:每次绘制前调用
ctx.lineCap = 'round'和ctx.lineJoin = 'round'让刮痕更自然
判断刮开面积触发中奖反馈
不能等用户刮完整个区域才提示中奖。通常设定一个阈值(如遮罩被擦除面积 ≥ 40%),实时检测并响应。
- 用
ctx.getImageData(0, 0, width, height)获取上层Canvas当前所有像素数据 - 遍历像素数组(每4个值为RGBA),统计alpha通道(data[i+3])为0的像素数量(即被擦除部分)
- 计算擦除比例:
erasedRatio = zeroAlphaCount / (width * height) - 当
erasedRatio >= 0.4时,停止监听、显示中奖弹窗,并可调用drawWinnerAnimation()增强反馈
兼容性与性能优化要点
真实项目中需兼顾流畅性和兼容性:
- 避免在
mousemove中频繁调用getImageData(开销大),改为每200ms节流检测一次 - 移动端必须处理
touchmove默认行为:e.preventDefault()防止页面滚动干扰 - 为提升响应速度,可对像素采样降频——比如每隔3像素取一个点,而非全量扫描
- 若只需简单判定(如刮到某个文字区域),可用
isPointInPath()配合预定义中奖区域路径,比全图采样更轻量
整个逻辑不依赖第三方库,纯原生Canvas即可完成。重点在于理解destination-out的合成含义:它让新绘制内容“挖掉”原有像素,露出下层——这正是刮刮卡的视觉本质。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











