使用globalCompositeOperation = 'source-in'时如何正确清空Canvas并重绘
问题根源
你的绘制逻辑问题出在globalCompositeOperation = 'source-in'的状态残留上:
source-in混合模式的规则是:新绘制的内容仅会保留和画布已有不透明区域重叠的部分- 你清空画布后,画布处于完全透明状态,原
drawface方法上来就将混合模式设置为source-in,此时绘制蒙版时因为画布没有已有内容,蒙版绘制结果全透明,后续再绘制人脸自然也没有内容显示
解决方案
调整drawface的绘制逻辑,用save()/restore()包裹绘制流程,先使用默认的source-over模式绘制蒙版,再切换为source-in绘制人脸,避免混合模式残留影响绘制效果。
修复后的代码
function drawface(){ // 保存当前画布上下文的全部状态(包括混合模式、变换矩阵等) this.ctx.save(); // 用默认混合模式绘制蒙版,保证蒙版能正常显示在清空后的画布上 this.ctx.globalCompositeOperation = 'source-over'; this.ctx.drawImage(msk, 0, 0, msk_w, msk_w, x, marg, h_c, h_c ); // 切换为source-in模式绘制人脸,实现蒙版裁剪效果 this.ctx.globalCompositeOperation = 'source-in'; this.ctx.drawImage(this.face, 0, 0, w_f, h_f, x+x_offset, marg+y_offset, h_c, h_c); // 恢复上下文原始状态,避免污染其他绘制逻辑 this.ctx.restore(); }
如果之前有对画布做过平移/缩放等变换,担心clearRect清空范围不对,可以同步优化resetCanvas方法:
function resetCanvas(){ this.ctx.save(); // 重置变换矩阵,确保清空范围覆盖整个画布 this.ctx.setTransform(1, 0, 0, 1, 0, 0); this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); this.ctx.restore(); }
调整后按照「清空画布→调用drawface重绘」的流程执行,就能正常实现拖拽时的人脸重绘效果。
内容的提问来源于stack exchange,提问作者Rom
相关产品推荐
相关产品推荐

