HTML canvas 剪辑路径是包含的还是独占的?

Are HTML canvas clip paths inclusive or exclusive?

我一直在为我们的 CQC 家庭自动化平台开发基于 Typescript 的触摸屏客户端,并且 运行 遇到了一些奇怪的事情。在很多地方,各种图形元素层叠在图像上。当需要更新屏幕的某些区域时,我设置一个剪辑区域并更新。

但我总是在所有内容周围画一条线,这是图像后面底层颜色填充的颜色。我当然责怪自己。但是,最后,我没有自杀,而是做了一个小测试程序。

这似乎表明 drawImage() 不包括剪辑路径边界,而颜色填充则包括。因此,在我正在更新的区域下方的图像部分上进行 blitting 并没有完全填充目标区域,而是在该区域周围留下一条线。

在那个简单的程序演示了这个问题之后,我返回并进行图像更新,我将剪辑区域扩大一倍,但其他一切都不用管它,现在一切正常了。我在 Chrome 和 Edge 中对此进行了测试,只是为了确保它不是某个错误,并且它们的行为完全相同。

St运行gely,我从未在文档中看到任何关于剪辑路径是否旨在排除或包含边界的声明,但它肯定不应该是一种类型的一种方式原始的和其他人的另一种方式,对吗?

function drawRect(ctx, x, y, w, h) {
    ctx.moveTo(x, y);
    ctx.lineTo(x + w, y);
    ctx.lineTo(x + w, y + h);
    ctx.lineTo(x, y + h);
    ctx.lineTo(x, y);
}

function init()
{
    var canvas = document.getElementById("output");
    canvas.style.width = 480;
    canvas.style.height = 480;
    canvas.width = 480;
    canvas.height = 480;

    var drawCtx = canvas.getContext("2d");
    drawCtx.translate(0.5, 0.5);

    var img = new Image();
    img.src = "test.jpg";
    img.onload = function() {

        // DRaw the image
        drawCtx.drawImage(img, 0, 0);

        // SEt a clip path
        drawCtx.beginPath();
        drawRect(drawCtx, 10, 10, 200, 200);
        drawCtx.clip();

        // Fill the whole area, which fills the clip area
        drawCtx.fillStyle = "black";
        drawCtx.fillRect(0, 0, 480, 480);

        // Draw the image again, which should fill the area
        drawCtx.drawImage(img, 0, 0);

        // But it ends up with a black line around it
    }
}

window.addEventListener("load", init, false);

我认为他们的行为是一样的。

剪辑区域不包括边框,但可以使用抗锯齿。

Chrome 没有使用这种技术,并且在裁剪时给出了锯齿状的线条。 (可能他们最近改变了)。

黑色细边框是合成操作的副作用。 剪辑区域跨越一个像素。所以 fillRect 将在所有地方绘制黑色,但边框将是 50% 黑色和 50% 透明,与第一个图像绘制合成。

第二个绘制图像被裁剪,在边框处使用 50% 的不透明度来模拟半像素。此时在剪辑边界你有:

图片 100% 黑色填充 50% 图片 50%

这会出现一个小的深色边框。

function drawRect(ctx, x, y, w, h) {
    ctx.moveTo(x, y);
    ctx.lineTo(x, y + h);
    ctx.lineTo(x + w, y + h);
    ctx.lineTo(x + w, y);
    ctx.closePath();
}

function init()
{
    var canvas = document.getElementById("output");
    canvas.style.width = 480;
    canvas.style.height = 480;
    canvas.width = 480;
    canvas.height = 480;

    var drawCtx = canvas.getContext("2d");
    drawCtx.translate(0.5, 0.5);

    var img = new Image();
    img.src = "http://fabricjs.com/assets/printio.png";
    img.onload = function() {

        // DRaw the image
        drawCtx.drawImage(img, 0, 0);

        // SEt a clip path
        drawCtx.beginPath();
        drawRect(drawCtx, 10, 10, 200, 200);
        drawCtx.clip();

        // Fill the whole area, which fills the clip area
        drawCtx.fillStyle = "black";
        drawCtx.fillRect(0, 0, 480, 480);

        // Draw the image again, which should fill the area
        drawCtx.drawImage(img, 0, 0);

        // But it ends up with a black line around it
    }
}

init();
<canvas id="output" />