javascript - 如何在 clip() 之后在 Canvas 中执行 clearRect()?

标签 javascript html5-canvas

我需要在 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(),它对我不起作用。

提前致谢, 凯萨万

最佳答案

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() 以便之后能够重置剪辑区域。
*它仍然可以通过设置 Canvas 宽度或高度来解锁,但这很糟糕吗?

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 而不是裁剪这会导致更清晰的抗锯齿效果,并且通常会带来更好的性能。但由于我不知道你为什么要使用 clip,所以我无法真正向你展示等效项。

关于javascript - 如何在 clip() 之后在 Canvas 中执行 clearRect()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56088068/

相关文章:

javascript - reactjs 中字典的正确 PropTypes 是什么

javascript - 如何在 PrimeNG 中使用 RowGroup 交换组位置?

canvas - CanvasRenderingContext2D 中的透明度组

javascript - Sketch.js pageX 未定义错误

javascript - 格式化数组

javascript - 当这两个浏览器完全独立时,将 window.open 对象从一个浏览器传递到另一个浏览器

Javascript - 交互式粒子 Logo 不起作用

javascript - 使用 createjs 制作 html5 视频

Javascript 替换为正则表达式模式问题

javascript - Canvas 绘制很慢