Canvas 画布创建透明的图像遮罩

Canvas 画布创建透明的图像遮罩,canvas,html5-canvas,masking,Canvas,Html5 Canvas,Masking,我有一个画布,用户可以使用我创建的画笔工具(鼠标向下或触摸)进行绘制。 我希望绘图区域由画布上的形状限制,例如,汉字的形状 该形状不是一个简单的形状,因此使用CanvasRenderingContext2D.clip()实际上不是一个选项 我的下一个解决方案是使用drawImage将遮罩图像绘制为PNG到画布上,然后将CanvasRenderingContext2D.GlobalComposite操作更改为“source Top”,以便笔刷仅在遮罩图像内绘制 这是我一直坚持的要求——在画布的最终

我有一个画布,用户可以使用我创建的画笔工具(鼠标向下或触摸)进行绘制。 我希望绘图区域由画布上的形状限制,例如,汉字的形状

该形状不是一个简单的形状,因此使用CanvasRenderingContext2D.clip()实际上不是一个选项

我的下一个解决方案是使用drawImage将遮罩图像绘制为PNG到画布上,然后将CanvasRenderingContext2D.GlobalComposite操作更改为“source Top”,以便笔刷仅在遮罩图像内绘制

这是我一直坚持的要求——在画布的最终输出中,我不想看到遮罩图像

我可以接受将遮罩图像设置为非常低的alpha值,这样几乎看不见

因此,我尝试在放置图像之前设置全局alpha,然后在笔刷开始绘制时恢复它

但是,绘制的重叠也与遮罩图像具有相同的alpha,但我希望它处于完整状态

有没有其他我不知道的方法来实现这一点?

如何创建“不可见”遮罩如果您想避免遮罩显示,可以将css背景设置为白色,并用白色填充遮罩。这样面具就“看不见了”。如果需要透明度,则在完成所有绘图后,可以使用
context.getImageData
使所有剩余的白色像素透明

但是…合成只会影响现有图形与新图形,因此问题是如果你的应用程序以增量方式添加像素,你将不得不进行大量的保存+重画,以使用合成来限制像素。这是因为在当前合成周期中,上次绘制的新像素将成为现有像素

所以…再看看
上下文。clip
将新图形(画笔笔划)限制在定义的剪切路径中。将复杂形状简化为画布路径并不困难。如果您有大量的字符来创建路径,那么考虑Adobe Idtuulor加上Mike Swanson的插件,将SVG路径导出为画布路径。 如何创建“不可见”遮罩如果要避免遮罩显示,可以将css背景设置为白色,并用白色填充遮罩。这样面具就“看不见了”。如果需要透明度,则在完成所有绘图后,可以使用
context.getImageData
使所有剩余的白色像素透明

但是…合成只会影响现有图形与新图形,因此问题是如果你的应用程序以增量方式添加像素,你将不得不进行大量的保存+重画,以使用合成来限制像素。这是因为在当前合成周期中,上次绘制的新像素将成为现有像素


所以…再看看
上下文。clip
将新图形(画笔笔划)限制在定义的剪切路径中。将复杂形状简化为画布路径并不困难。如果您有大量的字符来创建路径,那么考虑Adobe Idtuulor加上Mike Swanson的插件,将SVG路径导出为画布路径。 @markE的解决方案适用于一小部分预定义字符,您可以在之前处理这些字符

不幸的是,虽然文本是矢量绘制操作,但canvas Context2d中仅有的两个方法是and,这不允许我们在Path2D对象中包含该方法所需的文本

因此,如果您不能进行这种预处理,我认为这是
clip()
的一个好选择。 这将涉及使用2个画布,一个用于用户的绘图,另一个用于剪裁/渲染。(这里我甚至使用了第三个用于剪切遮罩,但它也可以是一个带有透明光栅png的
标记)

globalComposite操作
模式下的
source将仅在已绘制像素的位置绘制新绘制的像素。因此,第一个形状(剪裁遮罩)将不可见

var ctx=canvas.getContext('2d');
//为绘画创建缓冲画布
var paint=canvas.cloneNode(真);
var paint_ctx=paint.getContext('2d');
//为剪辑遮罩创建另一个缓冲区画布
//(也可以是标记中的光栅png
var clip_mask=canvas.cloneNode(true);
var clip_ctx=clip_mask.getContext('2d');
var clip=function(){
//清除可见画布
ctx.clearRect(0,0,canvas.width,canvas.height);
//绘制剪切遮罩
ctx.drawImage(剪辑遮罩,0,0);
//更改gCO
ctx.globalCompositeOperation=“来源于”;
//画出用户的画
ctx.drawImage(油漆,0,0);
//始终重置默认gCO
ctx.globalCompositeOperation=“源代码结束”;
//显示剪裁区域的笔划
如果(冲程检查){
Strokemack();
}
};
//
//用户的绘画方法
//
var doPaint=函数(x,y){
paint_ctx.beginPath();
绘制弧(x-3.5,y-3.5,7,Math.PI,-Math.PI);
油漆(ctx.fill)();
夹子();
};
canvas.onmousemove=函数(evt){
var rect=this.getBoundingClientRect();
var x=evt.clientX-rect.left;
var y=evt.clientY-rect.top;
doPaint(x,y);
};
//
//裁剪掩模方法
//
//初始化剪辑掩码
var initClip=function(){
clip_ctx.font=“150px无衬线”;
clip_ctx.textbreeline=“top”;
clip_ctx.textAlign=“中心”;
updateClip();
};
//更新剪辑遮罩
var updateClip=function(){
var val=字符值;
clip_ctx.clearRect(0,0,clip_mask.width,clip_mask.height);
变量x=(剪辑宽度/2);
clip_ctx.fillText(val,x,10);
paint_ctx.clearRect(0,0,paint.width,paint.height);
夹子();
};
//听文本输入
char.oninput=char.onchange=function(){
var val=该值;
//限于