canvas无原生遮罩,但可通过globalcompositeoperation(如destination-out挖空、source-in贴图)和clip()实现剪切效果,配合dpr适配、纯色涂层、触摸事件处理等细节确保稳定可用。

Canvas 本身没有原生“遮罩层”概念,但通过 globalCompositeOperation 可以精准控制像素级绘制逻辑,实现等效的剪切(裁剪)效果。核心不是覆盖颜色,而是决定“新画的内容和已有内容在哪些位置保留、哪些位置清除”。
destination-out:挖空已有内容,实现“镂空式”剪切
这是最常用也最直观的剪切模式。它让新绘制的形状成为“橡皮擦”,把画布上已存在的、与该形状重叠的不透明像素清为完全透明。
- 适用场景:圆形头像裁剪、刮刮乐涂层擦除、文字镂空背景、自定义路径挖空
- 关键操作顺序:先绘制底图 → 设置
ctx.globalCompositeOperation = 'destination-out'→ 绘制遮罩形状(如圆、矩形、路径)→ 调用fill()或stroke() - 注意:必须在绘制遮罩形状前设置该模式,且只影响后续绘制;若底图未铺满画布,建议先渲染到底层离屏 canvas 再统一处理,避免误擦空白区域
source-in:限制新内容显示范围,实现“贴图式”剪切
与 destination-out 相反,它让新绘制的内容(如图片或渐变)只在旧内容(如路径、文字)的非透明区域内显示,其余部分自动透明。
- 适用场景:将一张照片严格限制在五角星路径内显示、用文字形状作为图像容器
- 典型流程:先用
fillText()或fill()绘制遮罩形状(如文字或路径)→ 设置ctx.globalCompositeOperation = 'source-in'→drawImage()绘制目标图像 - 优势:无需预设底图,图像直接被“装进”形状里,适合动态生成内容
搭配 clip() 实现更轻量、不可逆的区域限定
clip() 不依赖合成模式,而是直接修改当前裁剪路径——之后所有绘制都自动被限制在该路径内,路径外内容不渲染也不占用像素。
- 适用场景:固定区域反复绘制(如仪表盘刻度、滚动列表视口)、性能敏感的局部更新
- 使用要点:调用
beginPath()→ 构建路径(arc(),rect(),lineTo()等)→clip()→ 后续fill()/drawImage()自动受限 - 区别:clip 是“硬裁剪”,不影响已有像素;globalCompositeOperation 是“像素混合”,会修改画布数据,适合需要交互擦除或动态蒙版的场景
实际应用中的关键细节
真正让遮罩效果稳定可用,离不开几个容易忽略的实操要点:
- 涂层必须是纯色填充(如
ctx.fillStyle = '#000'),避免用rgba(0,0,0,0.5)—— 半透涂层被destination-out擦除后会残留灰影 - 高 DPR 设备(如 iPhone)需按
window.devicePixelRatio缩放 canvas 宽高,并用ctx.scale()校正绘图坐标,否则刮擦变细或错位 - 移动端务必监听
touchstart/touchmove并调用e.preventDefault(),否则页面滚动会中断连续刮擦 - 判断刮开完成?可定期用
getImageData()获取涂层区域 alpha 值,统计透明像素占比,达阈值即触发中奖逻辑











