如何在 Chrome Windows 下的 html5 画布中消除锯齿 clip() 边缘?

2022-01-17 00:00:00 google-chrome html html5-canvas clip

我在画布上使用 clip() 函数.

I'm using the clip() function on a canvas.

结果:

您可以看到 chrome 版本的边缘有可怕的锯齿/锯齿.我该如何解决这个问题?

As you can see the chrome version has horrible jaggies / aliasing along the edges. How do I fix this?

要重现的代码:

http://jsfiddle.net/ZRA76/ :

<canvas id="test" width="300" height="300"></canvas>​

<script type="text/javascript">
    cv = document.getElementById("test");
    ctx = cv.getContext("2d");

    var im = new Image();
    im.onload = function () {
        ctx.beginPath();
        ctx.arc(110, 110, 100, 0, 2*Math.PI, true);
        ctx.clip();
        ctx.drawImage(im, 0, 0);
    }
    im.src = "http://placekitten.com/300/300";
</script>

推荐答案

如果您正在执行复杂的分层绘图,您可以使用 globalCompositeOperation 在第二个临时画布中模拟剪辑.然后,您可以使用 drawImage 将临时画布复制回原始画布.我不能保证这种方法的性能,但这是我知道的唯一获得你想要的方法.

If you're doing complex, layered drawing, you can use globalCompositeOperation to emulate clipping in a second, scratch canvas. You can then use drawImage to copy the scratch canvas back into the original canvas. I can't guarantee the performance of this approach, but it's the only way I know to get what you want.

//set-up - probably only needs to be done once
var scratchCanvas = document.createElement('canvas');
scratchCanvas.width = 100;
scratchCanvas.height = 100;
var scratchCtx = scratchCanvas.getContext('2d');


//drawing code
scratchCtx.clearRect(0, 0, scratchCanvas.width, scratchCanvas.height);

scratchCtx.globalCompositeOperation = 'source-over'; //default

//Do whatever drawing you want. In your case, draw your image.
scratchCtx.drawImage(imageToCrop, ...);


//As long as we can represent our clipping region as a single path, 
//we can perform our clipping by using a non-default composite operation.
//You can think of destination-in as "write alpha". It will not touch
//the color channel of the canvas, but will replace the alpha channel.
//(Actually, it will multiply the already drawn alpha with the alpha
//currently being drawn - meaning that things look good where two anti-
//aliased pixels overlap.)
//
//If you can't represent the clipping region as a single path, you can
//always draw your clip shape into yet another scratch canvas.

scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacity
scratchCtx.globalCompositeOperation = 'destination-in';
scratchCtx.beginPath();
scratchCtx.arc(50, 50, 50, 0, 2 * Math.PI, true);
scratchCtx.closePath();
scratchCtx.fill();


//Now that we have a nice, cropped image, we can draw it in our
//actual canvas. We can even draw it over top existing pixels, and
//everything will look great!

ctx.drawImage(scratchCanvas, ...);

我们在草稿画布中执行此操作的原因是,destination-in 是一个非常具有破坏性的操作.如果你已经在主画布上画了一些东西(也许你在背景中放了一个漂亮的渐变),然后想画一个剪裁的图像,剪裁圆也会剪掉你已经画的所有东西.当然,如果您的特殊情况比较简单(也许您想要绘制的只是一张剪裁的图像),那么您可以放弃草稿画布.

The reason that we do this in a scratch canvas is that destination-in is a pretty destructive operation. If you had already drawn some things into the main canvas (perhaps you put down a nice gradient in the background), and then wanted to draw a clipped image, the clipping circle would also clip out everything you had already drawn. Of course, if your particular situation is simpler (maybe ALL you want to draw is a clipped image), then you can forego the scratch canvas.

您可以在 我的演示页面上尝试不同的剪辑模式.底行(带有渐变)对您来说不太有用,但顶行(带有圆形和正方形)更相关.

You can play around with the different clipping modes on my demo page. The bottom row (with the gradients) is not too useful to you, but the top row (with the circle and square) is much more relevant.

编辑

糟糕,我不小心fork 你的 JSFiddle 来演示这项技术.

Whoops, I accidentally forked your JSFiddle to demonstrate the technique.

相关文章