2012-03-02 78 views
29

我在画布上使用了clip()函数。如何在Chrome Windows下的HTML5画布中反锯齿clip()边缘?

结果: using canvas clip in various browsers

正如你可以看到Chrome版本有可怕的锯齿/走样沿边缘。我该如何解决?

代码重现:

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> 
+0

我也遇到了这个问题。我所做的就是在图像的相同位置绘制一个圆圈,在它后面,半径为1或2 px。保持颜色相似,然后去“反锯齿”图像剪辑。 – Automatico 2012-07-23 14:31:13

回答

2
从答案

Can I turn off antialiasing on an HTML <canvas> element?看来,它是针对特定浏览器。它甚至是google代码铬项目上的一个活跃bug report。对不起,现在看起来你运气不好。

+1

现在,错误修复处于[chrome dashboard](https://www.chromestatus.com/features/4871530282483712)的开发状态。 正如[问题](https://code.google.com/p/chromium/issues/detail?id=422984)中所述,其他浏览器(IE,Firefox,Safari)'clip()'是反锯齿的。 – sapics 2015-09-25 06:06:22

-1

使用svg剪辑。像魅力一样工作,但不便于使用。

5

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

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

context.globalCompositeOperation = 'source-atop'; 

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

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

+0

这个解决方案表现非常好,谢谢。剪辑的一个弧和中风的一个弧。简单。我相信对于这个问题,临时画布解决方案太复杂和缓慢,除非你有不想要中风的问题。 – mattdlockyer 2013-07-23 19:40:34

+0

当我通过画布运行视频时,我能够应用此功能以及“背部画布”技术,以减少令人讨厌的锯齿状边缘:http://codepen.io/paceaux/pen/egLOeR 谢谢分享。 – paceaux 2017-02-10 19:18:12

12

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

+0

这么棒的主意!谢谢!! – Keith 2013-02-17 22:37:17

+0

我一直在努力今天超过一个小时,这样一个简单而神奇的解决方案:) – trueicecold 2014-08-13 14:53:44

+0

是的,这,CLEVER,<3! – 2014-09-05 22:33:43

22

如果您正在执行复杂的分层绘制,则可以使用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来演示该技术。

+0

你先生,救了我的一天! – enyce12 2014-07-10 14:55:59

+0

谢谢你!其作品!!! – 2016-05-16 17:54:48