在画布中使用Clip导致像素

时间:2016-06-30 11:22:48

标签: javascript canvas html5-canvas

我正在尝试使用context.clip()从另一个剪切绘制弧并填充剪切结果。 但当我剪辑部分&填充它,它给出像素化填充。

  var ctx = document.getElementById("canvas").getContext("2d");
  var x = 150 ; 
  var y = 150 ;
  var r = 100 ;

    ctx.save() ;
    ctx.translate(x,y) ;

    ctx.beginPath() ;
    ctx.arc(0,0,r,0,2*Math.PI);
    ctx.closePath() ;
    ctx.fillStyle = "cyan" ;
    ctx.fill() ;
    ctx.lineWidth = 10;
    ctx.stroke();
    ctx.restore() ;

    ctx.save() ;
    ctx.clip() ;
    ctx.translate(x,y);

    ctx.beginPath();
    ctx.moveTo(r,-r-10);
    ctx.arc(0,-r-10,r,0,Math.PI*2);
    ctx.closePath();
    ctx.fillStyle = "#f2f2f2";
    ctx.fill();
    ctx.lineWidth = 1;
    ctx.stroke();
    ctx.restore();

https://jsfiddle.net/x0d0n40z/1/

3 个答案:

答案 0 :(得分:2)

无需clip() / save() / restore()的替代方法是使用合成的几个步骤。

在某些浏览器中,剪切蒙版是消除锯齿的,而在其他浏览器中则没有。为了获得一致性(在某些情况下还有性能,因为保存 - 剪辑 - 恢复是相对昂贵的操作),如果可能的话,首选使用合成。

在这种情况下:

  • 以目标颜色填充主弧
  • 定义剪裁弧
  • 将复合模式更改为destination-out并填充(将剪切主要)
  • 将复合模式更改为source-atop和笔划(将轮廓切割)
  • 将复合模式更改为source-over并描绘主圆的轮廓

实施例

更新:简化步骤(最后一步合并到流程中,参考评论)。我还选择演示Path2D的使用,因为我们可以重用对象而不会干扰普通上下文中的路径 -

var ctx = c.getContext("2d"),
    p = new Path2D(),          // this will store main shape for reuse
    x = 75, y = 75, radius = 70;

// main arc
p.arc(x, y, radius, 0, 6.28);  // store to path object
ctx.fillStyle = "cyan";
ctx.fill(p);                   // fill path object

// clip top arc
ctx.globalCompositeOperation = "source-atop";
ctx.arc(x, y - radius, radius, 0, 6.28);
ctx.fillStyle = "#09f";
ctx.fill();
ctx.lineWidth = 5;
ctx.stroke();

// stroke main arc
ctx.globalCompositeOperation = "source-over";
ctx.stroke(p);                 // stroke path object
body {background:#e9e9e9}
<canvas id=c></canvas>

旧版本:

var ctx = c.getContext("2d"),
    x = 75, y = 75, radius = 70;

// main arc
ctx.arc(x, y, radius, 0, 6.28);
ctx.fillStyle = "cyan";
ctx.fill();

// clipping arc
ctx.beginPath();
ctx.arc(x, y - radius, radius, 0, 6.28);

// cut step
ctx.globalCompositeOperation = "destination-out";
ctx.fill();

// stroke gap step
ctx.globalCompositeOperation = "source-atop";
ctx.lineWidth = 10;
ctx.stroke();

// stroke whole outline
ctx.globalCompositeOperation = "source-over";
ctx.beginPath();
ctx.arc(x, y, radius, 0, 6.28);
ctx.lineWidth = 5;
ctx.stroke();

// if you want to color the clip then use this:
ctx.globalCompositeOperation = "destination-atop";
ctx.fillStyle = "#09f";
ctx.fill();
body {background:#e9e9e9}
<canvas id=c></canvas>

答案 1 :(得分:0)

问题是剪辑边界没有被反对。

要解决此问题,您可以在不使用剪辑的情况下渲染形状。 ctx.arc方法允许您设置开始和结束角度,以便通过填充两个弧来获取插入。

您需要获取剪辑圆和插入圆截取的角度。

对于这种情况,它非常简单。首先得到圆之间的距离,以及从一个到另一个的角度。这仅适用于两个半径相同的圆。

http://getbootstrap.com/customize/

现在你有了角度和距离,截距是距离和半径之间的简单关系

var c = {x:?,y:?}; // circle one location
var c1 = {x:?,y:?}; // circle two location
var radius = ?; // radius of both
var angle = Math.atan2(c1.y - c.y, c1.x - c.x);  // get the angle from one to the next
var dist = Math.hypot(c1.x - c.x, c1.y - c.y); // get the distance. NOTE IE does not have hypot so do it the normal way with Math.sqrt....

现在您可以使用该角度绘制两个弧

var iAngle = Math.acos(dist / 2 / radius); // the angle from the line between the circles
                                          // to the intercepts

没有太多可以防止锯齿影响剪辑区域。实现剪切的另一种方法是使用ctx.globalCompositeOperation渲染蒙版。您可以屏蔽进出,以及更多选项。当裁剪区域变得更复杂时,这将是更好的解决方案。

答案 2 :(得分:0)

我终于找到了纠正错误的正确方法。 继承了我想要的清晰结果https://jsfiddle.net/x0d0n40z/6/

代码:

var ctx = document.getElementById("canvas").getContext("2d");
var r = 50    
x = ctx.canvas.width/2;
y = ctx.canvas.height/2;
var offset = 60;

ctx.save();
ctx.setTransform(1,0,0,1.5,x,y);
ctx.beginPath();
ctx.arc(0,0,r,0,2*Math.PI);
ctx.stroke();
ctx.clip();


ctx.beginPath();
ctx.arc(0,0,r,0,2*Math.PI,false);
ctx.fillStyle = "cyan";
ctx.fill();

ctx.setTransform(1, 0, 0, 1, x, y);
ctx.beginPath();
ctx.arc(0,-offset,r,0,2*Math.PI,false);
ctx.fillStyle = "#f2f2f2";
ctx.fill();
ctx.lineWidth = 1 ;
ctx.stroke();

ctx.setTransform(1,0,0,1.5,x,y);
ctx.beginPath();
ctx.arc(0,0,r,0,2*Math.PI,false);
ctx.lineWidth = 3 ;
ctx.stroke();

ctx.restore();

来自我是否学会使用剪辑:http://www.html5canvastutorials.com/advanced/html5-canvas-clipping-region-tutorial/