You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:36:03