如何在Chrome Windows下的html5画布中对别名剪贴边缘?

时间:2012-03-02 15:51:43

标签: html5 google-chrome html5-canvas clip

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

结果: using canvas clip in various browsers

正如你所看到的那样,镀铬版本沿着边缘有可怕的锯齿/锯齿。我该如何解决这个问题?

重现的代码:

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>

5 个答案:

答案 0 :(得分:24)

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

//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, ...);

我们在临时画布中执行此操作的原因是目标输入是一种非常具有破坏性的操作。如果你已经在主画布中绘制了一些东西(也许你在背景中放下了一个漂亮的渐变),然后想要绘制一个剪裁的图像,那么剪裁圆圈也会剪掉你已绘制的所有内容。当然,如果你的特殊情况比较简单(也许你想画的是一个剪裁的图像),那么你可以放弃刮刮画布。

您可以在my demo page上使用不同的剪辑模式。底行(带有渐变)对你来说不是很有用,但是顶行(带圆圈和正方形)更相关。

修改

哎呀,我不小心forked your JSFiddle来演示这项技术。

答案 1 :(得分:12)

我对此的修复是在绘制图像后在相同半径绘制一个薄的(2px)白色笔划。它很好地掩盖了别名,并且在浏览器中看起来很好。

答案 2 :(得分:5)

我遇到了与Chrome和clip()相同的问题。

在我的情况下,我通过设置canvas globalCompositeOperation来实现更好的浏览器兼容性。

context.globalCompositeOperation = 'source-atop';

所以在这种情况下画出你的形状,一个圆圈。然后切换到'source-atop'并绘制你的小猫图像。

请注意,这是基本绘图的快速修复,并假设为空白画布。之前的画布绘图会影响剪辑。

答案 3 :(得分:2)

来自Can I turn off antialiasing on an HTML <canvas> element?上的答案,它似乎是浏览器特定的。它甚至是Google代码铬项目中的有效bug report。对不起,但现在看来你运气不好。

答案 4 :(得分:-1)

使用svg剪辑。像魅力一样,但使用起来不太方便。