1

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

但我总是在所有东西周围都有一条线,这是图像后面的基础颜色填充的颜色。我当然责备自己。但是,最后,我没有自杀,而是做了一个小测试程序。

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

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

奇怪的是,我从来没有在文档中看到任何关于剪辑路径是排他还是包含边界的声明,但肯定它不应该是一种原始类型的一种方式,而另一种类型的原始方式是另一种方式,对吧?

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);
4

1 回答 1

1

我认为他们的行为相同。

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

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" />

于 2017-07-06T10:18:36.933 回答