我需要在canvas中执行clip()之后执行clearRect()。不幸的是,它对我不起作用。
如果我排除clip()的意思,则clearRect()可以正常工作。
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(0, 0, 300, 150);
ctx.clip(); //after removing clip() clearRect() working
ctx.clearRect(20, 20, 100, 50);
</script>
我需要在执行clip()之后执行clearRect()。这可能吗?
请找到fiddle
public canvasClip(options: BaseAttibutes): void {
this.ctx.save();
this.ctx.rect(options.x, options.y, options.width, options.height);
this.ctx.clip();
}
public clearRect(rect: Rect): void {
this.ctx.restore();
this.ctx.clearRect(rect.x, rect.y, rect.width, rect.height);
};
如果我在调用canvasClip()之后调用了clearRect(),那么它对我不起作用。
先谢谢了, Kesavan
答案 0 :(得分:2)
clip()
的工作方式是采用当前的子路径声明,所有不应该在其填充区域中的内容都将从绘图区域中丢弃。也就是说,如果您再次在该区域之外绘制某些内容,则该内容将不会显示在上下文中。
我想您的困惑来自fillRect()
。此方法有点特殊,它会创建一个仅用于此方法的临时矩形子路径(strokeRect
与此相同)。
这是一个直观的例子,说明了什么:
const ctx = canvas.getContext('2d');
// declare a sub-path
ctx.beginPath();
ctx.arc(50,50,30,0,Math.PI*2); // circle
// this will discard our circle
ctx.fillStyle = 'red';
ctx.fillRect(120, 50, 30, 30);
// wait a bit to show it has been discarded
setTimeout(() => {
ctx.fillStyle = 'blue';
ctx.fill(); // this draws only the circle,
// the internal rect() in fillRect() has disappeared,
// otherwise it would be blue now
}, 1000);
canvas {border: 1px solid}
<canvas id="canvas" width="500"></canvas>
因此,在调用clip()
之前,您实际上并未在上下文中声明任何子路径,并且新的绘图区域(未绘制)是0x0px路径(即它不存在)。每个绘图操作(并且clearRect
是一个)将不起作用。
const ctx = canvas.getContext('2d');
// what OP did is equivalent to
ctx.beginPath();
ctx.clip(); // clip a non-existent sub-path
// you can try to draw, it won't work
ctx.arc(50,50,30,0,Math.PI*2);
ctx.fill();
ctx.fillRect(120, 50, 30, 30);
canvas {border: 1px solid}
<canvas id="canvas" width="500"></canvas>
唯一仍然有效的方法是putImageData
。
并且由于您只能删除绘图区域,因此通过剪切此非区域,您实际上将上下文锁定在此状态。*
因此,在使用clip()
之前,请务必先调用ctx.save()
,以便以后能够重置剪切区域。
* 还是可以通过设置画布的宽度或高度将其解锁,但这不好吗?
const ctx = canvas.getContext('2d');
// so we can reset our clipping area
ctx.save();
ctx.fillStyle = "red";
// use `rect()` which does add to the current sub-path
ctx.rect(0, 0, 300, 150);
ctx.fill();
ctx.clip();
ctx.clearRect(20, 20, 100, 50); // now we can clear
ctx.restore(); // remove the clipping area
ctx.fillRect(320, 0, 20, 20); // now we can draw anywhere
canvas {border: 1px solid}
<canvas id="canvas" width="500"></canvas>
但是请注意,在大多数情况下,最好不要使用裁剪compositing,这样可以产生更清晰的抗锯齿效果,并且通常可以带来更好的性能。但是由于我不知道您为什么要使用剪辑,因此我无法真正向您展示等效项。