如何使globalCompositeOperation
仅影响save / restore()上下文中的内容?
例如,红色矩形波纹管正受到“目的地在上”运算符的影响。预期要做的是用红色矩形填充画布,并在其上看到黑色圆圈。而且发生的是红色矩形也被遮盖了。
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let size1 = 350;
let size2 = 150;
let size3 = 154;
canvas.width = size1;
canvas.height = size1;
canvas.style.width = size1+'px';
canvas.style.height = size1+'px';
//red rectangle
ctx.fillStyle = "red";
ctx.beginPath();
ctx.rect(0, 0, size1, size1);
ctx.fill();
// save the context state
ctx.save();
//black circle
ctx.fillStyle = "black";
ctx.beginPath();
ctx.ellipse(size2, size2, size2, size2, 0, 0, 6.28);
ctx.fill();
//mask
//shouldnt it mask only the shape before?
//why is it masking the red rectangle outside save/restore() context?
ctx.globalCompositeOperation="destination-atop";
ctx.beginPath();
ctx.ellipse(size3, size3, size3, size3, 0, 0, 6.28);
ctx.fill();
ctx.restore();
<canvas id="canvas" />
我知道有一种方法可以创建多个画布以将它们组合起来,或者可以使用其他技术进行遮罩,但是我的主要问题是globalCompositeOperation
不尊重save / restore()上下文...
答案 0 :(得分:0)
save()
方法将2DContext的所有当前属性保存在已保存状态的堆栈中。 ({fillStyle
,strokeStyle
,font
,lineWidth
等)
restore()
将应用堆栈中最后保存的状态,同时将其从堆栈中删除。
这些方法都与画布上绘制的内容无关,它们只保存JS对象的某些属性(以及一些不可访问的属性,例如剪切区域)。
globalCompositeOperation
仅影响设置后的绘图操作。他们将与您在画布上绘制的内容有关。
save
和restore
根本无法帮助您实现目标。
您想要的是在单独的画布内容上进行合成,为此,最简单的方法是使用第二个画布元素:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let size1 = 350;
let size2 = 150;
let size3 = 154;
canvas.width = size1;
canvas.height = size1;
canvas.style.width = size1+'px';
canvas.style.height = size1+'px';
const copycanvas = canvas.cloneNode();
const copyctx = copycanvas.getContext('2d');
//red rectangle
ctx.fillStyle = "red";
ctx.beginPath();
ctx.rect(0, 0, size1, size1);
ctx.fill();
//draw the mask on the off-screen canvas
//black circle
copyctx.fillStyle = "black";
copyctx.beginPath();
copyctx.ellipse(size2, size2, size2, size2, 0, 0, 6.28);
copyctx.fill();
// I guess you didn't really want a source-atop gCO here
copyctx.globalCompositeOperation="source-out";
copyctx.beginPath();
copyctx.ellipse(size3, size3, size3, size3, 0, 0, 6.28);
copyctx.fill();
ctx.drawImage(copycanvas, 0, 0);
<canvas id="canvas" />
但是您也可以通过以其他顺序绘制完全在同一画布上进行精确绘制:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let size1 = 350;
let size2 = 150;
let size3 = 154;
canvas.width = size1;
canvas.height = size1;
canvas.style.width = size1+'px';
canvas.style.height = size1+'px';
//draw the mask first
//black circle
ctx.fillStyle = "black";
ctx.beginPath();
ctx.ellipse(size2, size2, size2, size2, 0, 0, 6.28);
ctx.fill();
// I guess you didn't really want a source-atop gCO here
ctx.globalCompositeOperation = "source-out";
ctx.beginPath();
ctx.ellipse(size3, size3, size3, size3, 0, 0, 6.28);
ctx.fill();
// finally, draw the background
ctx.globalCompositeOperation = "destination-over";
//red rectangle
ctx.fillStyle = "red";
ctx.beginPath();
ctx.rect(0, 0, size1, size1);
ctx.fill();
<canvas id="canvas" />