Javascript 绘制透明形状时覆盖在画布上绘制的图形

Javascript 绘制透明形状时覆盖在画布上绘制的图形,javascript,html,canvas,transparency,Javascript,Html,Canvas,Transparency,我看不出这篇文章已经发布了,所以就这样吧 假设我在画布上画了两个正方形 var c = document.getElementById('test'), ctx = c.getContext('2d'); ctx.fillStyle = "rgba(0,0,255,0.5)"; ctx.beginPath(); ctx.moveTo(25, 0); ctx.lineTo(50, 50); ctx.lineTo(0, 50); ctx.lineTo(25, 0); ctx.fill(); ctx.

我看不出这篇文章已经发布了,所以就这样吧

假设我在画布上画了两个正方形

var c = document.getElementById('test'), ctx = c.getContext('2d');
ctx.fillStyle = "rgba(0,0,255,0.5)";
ctx.beginPath();
ctx.moveTo(25, 0);
ctx.lineTo(50, 50);
ctx.lineTo(0, 50);
ctx.lineTo(25, 0);
ctx.fill();
ctx.fillStyle = "rgba(255,0,0,0.5)";
ctx.beginPath();
ctx.moveTo(50, 0);
ctx.lineTo(75, 50);
ctx.lineTo(25, 50);
ctx.lineTo(50, 0);
ctx.fill();
这将生成以下图像:

如果我将globalAlpha更改为0.5,我会得到以下结果:

但是,我想制作以下内容:

与中一样,所有像素都是透明的,并且它下面的任何图像都将显示,但是由红色三角形创建的像素将覆盖绘制它的现有蓝色三角形

而ctx.globalComposisteOperation在这种情况下似乎没有帮助,因为它还考虑了透明度和我想要保留两个方块的事实


当前的方法有什么方法可以做到这一点吗?

在绘制第二个矩形之前,可以清除该区域

var c=document.getElementById('game'),
ctx=c.getContext('2d');
ctx.globalAlpha=0.5;
ctx.fillStyle=“蓝色”;
ctx.fillRect(0,0,50,50);
//清除蓝色矩形的额外位
ctx.clearRect(25,25,25,25);
ctx.fillStyle=“红色”;
ctx.fillRect(25,25,50,50)

您可以在绘制第二个矩形之前清除该区域

var c=document.getElementById('game'),
ctx=c.getContext('2d');
ctx.globalAlpha=0.5;
ctx.fillStyle=“蓝色”;
ctx.fillRect(0,0,50,50);
//清除蓝色矩形的额外位
ctx.clearRect(25,25,25,25);
ctx.fillStyle=“红色”;
ctx.fillRect(25,25,50,50)

我真诚地建议只改变颜色,避免使用alpha

var c=document.getElementById('game'),
ctx=c.getContext('2d');
ctx.fillStyle=“#8080FF”;
ctx.fillRect(0,0,50,50);
ctx.fillStyle=“#ff8080”;
ctx.fillRect(25,25,50,50)

我真诚地建议只改变颜色,避免使用alpha

var c=document.getElementById('game'),
ctx=c.getContext('2d');
ctx.fillStyle=“#8080FF”;
ctx.fillRect(0,0,50,50);
ctx.fillStyle=“#ff8080”;
ctx.fillRect(25,25,50,50)
只需使用clip()获取当前路径,使用clearRect清除其中的所有内容,然后按正常方式绘制路径


只需使用clip()获取当前路径,使用clearRect清除其中的所有内容,然后按正常方式绘制路径。

在绘制红色三角形之前,使用合成清除红色三角形

使用合成比剪切稍微好一些,因为您不必清除剪辑。清除片段需要保存整个上下文状态,然后恢复该上下文状态,这涉及到许多属性。合成只需要前后更改1个属性

var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var cw=画布宽度;
var ch=画布高度;
//填充蓝色矩形
ctx.fillStyle=“rgba(0,0255,0.5)”;
ctx.beginPath();
ctx.moveTo(25,0);
ctx.lineTo(50,50);
ctx.lineTo(0,50);
ctx.lineTo(25,0);
ctx.fill();
//定义红色矩形路径
ctx.beginPath();
ctx.moveTo(50,0);
ctx.lineTo(75,50);
ctx.lineTo(25,50);
ctx.lineTo(50,0);
//使用合成清除红色矩形路径
ctx.globalCompositeOperation='destination-out';
ctx.fillStyle='black';
ctx.fill();
ctx.globalCompositeOperation='source-over';
//填充红色矩形
ctx.fillStyle=“rgba(255,0,0,0.5)”;
ctx.fill()
body{背景色:白色;}
#画布{边框:1px纯红;}

在绘制红色三角形之前,使用合成清除红色三角形

使用合成比剪切稍微好一些,因为您不必清除剪辑。清除片段需要保存整个上下文状态,然后恢复该上下文状态,这涉及到许多属性。合成只需要前后更改1个属性

var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var cw=画布宽度;
var ch=画布高度;
//填充蓝色矩形
ctx.fillStyle=“rgba(0,0255,0.5)”;
ctx.beginPath();
ctx.moveTo(25,0);
ctx.lineTo(50,50);
ctx.lineTo(0,50);
ctx.lineTo(25,0);
ctx.fill();
//定义红色矩形路径
ctx.beginPath();
ctx.moveTo(50,0);
ctx.lineTo(75,50);
ctx.lineTo(25,50);
ctx.lineTo(50,0);
//使用合成清除红色矩形路径
ctx.globalCompositeOperation='destination-out';
ctx.fillStyle='black';
ctx.fill();
ctx.globalCompositeOperation='source-over';
//填充红色矩形
ctx.fillStyle=“rgba(255,0,0,0.5)”;
ctx.fill()
body{背景色:白色;}
#画布{边框:1px纯红;}

@markE是对的,使用合成而不是剪裁(非常重)

然而,只有当您使用rgba颜色绘制所有内容时,他的解决方案才会起作用。也许我看错了你的问题,但是如果你是从一个不透明的形状开始,并且想要使它透明,那么你应该使用
copy
gCO和
globalAlpha
属性

这对性能的影响较小,因为
drawImage
fill
更快,并且允许您执行淡出效果;但这取决于你的需要

var ctx=c.getContext('2d');
//首字母蓝色
ctx.fillStyle=“#0000FF”;
ctx.beginPath();
ctx.moveTo(25,0);
ctx.lineTo(50,50);
ctx.lineTo(0,50);
ctx.lineTo(25,0);
ctx.fill();
setTimeout(函数drawRed(){
ctx.fillStyle=“#FF0000”;
ctx.beginPath();
ctx.moveTo(50,0);
ctx.lineTo(75,50);
ctx.lineTo(25,50);
ctx.lineTo(50,0);
ctx.fill();
}, 500);
btn.onclick=函数makeItTransparent(){
//如果我们要将其制作成动画,我们只会设置一次
ctx.globalCompositeOperation='copy';
ctx.globalAlpha=.8;
//自己画画布
ctx.drawImage(c,0,0);
//同样,在动画中,我们不会将其重置为默认值
ctx.globalAlpha=1;
ctx.globalCompositeOperation='source over';
};
/*棋盘背景*/
帆布{
背景图像:url(“数据:image/png;base64,iVBORw0KGgo
var c = document.getElementById('test'), ctx = c.getContext('2d');
ctx.save();
ctx.fillStyle = "rgba(0,0,255,0.5)";
ctx.beginPath();
ctx.moveTo(25, 0);
ctx.lineTo(50, 50);
ctx.lineTo(0, 50);
ctx.lineTo(25, 0);
ctx.fill();
ctx.fillStyle = "rgba(255,0,0,0.5)";
ctx.beginPath();
ctx.moveTo(50, 0);
ctx.lineTo(75, 50);
ctx.lineTo(25, 50);
ctx.lineTo(50, 0);
ctx.clip();
ctx.clearRect(0, 0, 100, 100);
ctx.fill();
ctx.restore();
// canvas is original canvas 
var layer = document.createElement("canvas");
layer.width = canvas.width;  // same size as original 
layer.height = canvas.height;
var ctx1 = layer.getContext("2d");
var tri = (x,c)=>{
    ctx1.fillStyle = c;
    ctx1.beginPath();
    ctx1.moveTo(25 + x, 0);
    ctx1.lineTo(50 + x, 50);
    ctx1.lineTo(0 + x, 50);
    ctx1.closePath();
    ctx1.fill();
}
tri(0,"#00f");
tri(25,"#f00");
ctx.globalAlpha = 0.5;
ctx.drawImage(layer,0,0);
ctx1 = undefined;
layer = undefined;