Canvas clearRect只在循环中第一次起作用,发生了什么?

时间:2016-11-29 19:52:21

标签: javascript jquery canvas

这不是完整的代码,其他部分只是大括号和一些函数。 它是循环中要做的主要部分。我想获得边界半径像角度的矩形,以查看画布下的内容。但我第一次得到clearRect。或者可能是他们只是没有显示,因为循环工作我需要的所有时间。

 function draw() {
            $document = $(document);
            canvas.width = $document.width();
            canvas.height = $document.height();

            ctx.fillStyle = "rgba(0,0,0, 0.6)";
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            var $layer = $('#hint-layer'),
                $arrows = $('.arrows', $layer);

            $arrows.empty();

            $(options.selector).each(function() {
                var $this = $(this);
                roundedRect(ctx,
                    $this.offset().left -5,
                    $this.offset().top -5,
                    $this.outerWidth() + 10,
                    $this.outerHeight() + 10
                    ,10);

                ctx.clip();
                ctx.clearRect(
                    $this.offset().left -5,
                    $this.offset().top -5,
                    $this.outerWidth() + 10,
                    $this.outerHeight() + 10
                );
    }

    function roundedRect(ctx,x,y,width,height,radius){
          ctx.beginPath();
          ctx.moveTo(x,y+radius);
          ctx.lineTo(x,y+height-radius);
          ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
          ctx.lineTo(x+width-radius,y+height);
          ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
          ctx.lineTo(x+width,y+radius);
          ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
          ctx.lineTo(x+radius,y);
          ctx.quadraticCurveTo(x,y,x,y+radius);
          ctx.stroke();
}

2 个答案:

答案 0 :(得分:1)

您需要使用ctx.save和ctx.restore重置剪辑

$(options.selector).each(function() {
    var jQ =$(this);
    roundedRect(ctx,
        jQ .offset() .left - 5,
        jQ .offset() .top - 5,
        jQ .outerWidth() + 10,
        jQ .outerHeight() + 10
        ,10
    );
    ctx.save(); // save current unclipped state
    ctx.clip();
    ctx.clearRect(
        jQ .offset() .left - 5,
        jQ .offset() .top - 5,
        jQ .outerWidth() + 10,
        jQ .outerHeight() + 10
    );
    ctx.restore(); // remove the clip by restoring to unclipped state.
}

答案 1 :(得分:0)

CanvasContext2D clip方法调用会在您连续调用它时累积。

它的方式使得任何新的调用仅在它与先前剪切的部分折叠的情况下才会发生。

由于一张价值1000字的图片,我今天早上遇到了一些麻烦,这里有一个:



var ctx1 = c.getContext('2d');
var c2 = c.cloneNode();
var ctx2 = c2.getContext('2d');
ctx1.strokeStyle = '#CCC';

roundedRect(ctx2, 20, 40, 50, 50, 10);
ctx2.clip();
ctx2.fillStyle = 'red';
ctx2.fillRect(0, 0, c.width, c.height);

roundedRect(ctx1, 20, 40, 50, 50, 10);
ctx1.stroke();
// make a new overlapping clip
roundedRect(ctx2, 60, 60, 50, 50, 10);
ctx2.clip();
ctx2.fillStyle = 'green';
ctx2.fillRect(0, 0, c.width, c.height);

roundedRect(ctx1, 60, 60, 50, 50, 10);
ctx1.stroke();

// make a new completely off clip
roundedRect(ctx2, 160, 90, 50, 50, 10);
ctx2.clip();
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, c.width, c.height);

roundedRect(ctx1, 160, 90, 50, 50, 10);
ctx1.stroke();

ctx1.drawImage(c2, 0, 0);

function roundedRect(ctx, x, y, width, height, radius) {
  ctx.beginPath();
  ctx.moveTo(x, y + radius);
  ctx.lineTo(x, y + height - radius);
  ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
  ctx.lineTo(x + width - radius, y + height);
  ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
  ctx.lineTo(x + width, y + radius);
  ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
  ctx.lineTo(x + radius, y);
  ctx.quadraticCurveTo(x, y, x, y + radius);
  //          ctx.stroke();
}

<canvas id="c"></canvas>
&#13;
&#13;
&#13;

现在,删除裁剪区域的唯一两种方法是重置整个上下文,方法是设置画布的widthheight参数,或者调用{{1在ctx.save()clip()之前,您不再需要它了。
但是,一般情况下我反对ctx.restore(),当可以避免时:在绘制不在像素网格上的形状时,浏览器会创建一些会穿过剪裁区域的抗锯齿工件,如果您在同一位置绘制多次,将会累积,ruin your drawings,+保存/恢复将保存您的所有上下文属性,这通常是不需要的+它通常很难保持你保存/恢复的状态。

相反,人们应该更喜欢globalCompositeOperation。由于你想要的是一个自定义形状的橡皮擦,clip合成模式是你需要的:

&#13;
&#13;
destination-out
&#13;
var ctx = c.getContext('2d');
// start with a fully black canvas
ctx.fillRect(0, 0, c.width, c.height);
// set the gCO to source-out
ctx.globalCompositeOperation = 'destination-out';
// custom eraser
roundedRect(ctx, 20, 40, 50, 50, 10);
ctx.fill()
roundedRect(ctx, 60, 60, 50, 50, 10);
ctx.fill()
roundedRect(ctx, 160, 90, 50, 50, 10);
ctx.fill();
// reset our gCO
ctx.globalCompositeOpeartion = 'source-over';


function roundedRect(ctx, x, y, width, height, radius) {
  ctx.beginPath();
  ctx.moveTo(x, y + radius);
  ctx.lineTo(x, y + height - radius);
  ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
  ctx.lineTo(x + width - radius, y + height);
  ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
  ctx.lineTo(x + width, y + radius);
  ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
  ctx.lineTo(x + radius, y);
  ctx.quadraticCurveTo(x, y, x, y + radius);
  //          ctx.stroke();
}
&#13;
body{
    background-color: ivory;
  }
&#13;
&#13;
&#13;