在画布中每个上下文调用多个剪辑

时间:2014-11-17 11:40:56

标签: javascript html canvas html5-canvas

我似乎无法在画布上进行第二次剪辑调用。见小提琴:http://jsfiddle.net/m2hL17nu/ 请注意第一个径向渐变是如何被剪裁但第二个渐变渐变是

我看过Can you have multiple clipping regions in an HTML Canvas?但是保存还原似乎还没有让下一个clip()工作。

提前感谢您的帮助。请参阅以下代码:

var x1 = 300,
    y1 = 100,
    x2 = 50,
    y2 = 50,
    r = 20;

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
function createRadialGradient (xa, ya, xb, yb, r) {
    var grd = context.createRadialGradient(xa, ya, 0, xb, yb, r);
    grd.addColorStop(0, 'rgba(0,0,0,1)');
    grd.addColorStop(1, 'rgba(0,0,0,0)');
    context.fillStyle = grd;
    context.fill();
}
context.save();
context.rect(x1-r,y1-r,r,r);
context.clip();
context.rect(0, 0, canvas.width, canvas.height);
createRadialGradient(x1, y1, x1, y1, r);

context.restore();

context.save();
context.rect(x2-r,y2,r,r);
context.strokeStyle = 'black';
context.clip();
context.rect(0, 0, canvas.width, canvas.height);
createRadialGradient(x2, y2, x2, y2, r);

context.stroke();

2 个答案:

答案 0 :(得分:3)

在绘制剪辑之前和剪辑()方法之后,你应该使用beginPath()和closePath():

var x1 = 300,
    y1 = 100,
    x2 = 50,
    y2 = 50,
    r = 20;

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
function createRadialGradient (xa, ya, xb, yb, r) {
    var grd = context.createRadialGradient(xa, ya, 0, xb, yb, r);
    grd.addColorStop(0, 'rgba(0,0,0,1)');
    grd.addColorStop(1, 'rgba(0,0,0,0)');
    context.fillStyle = grd;
    context.fill();
}
context.save();
context.beginPath();
context.rect(x1-r,y1-r,r,r);
context.closePath();
context.clip();
context.rect(0, 0, canvas.width, canvas.height);
createRadialGradient(x1, y1, x1, y1, r);

context.restore();

context.save();
context.beginPath();
context.rect(x2-r,y2,r,r);
context.closePath();
context.clip();
context.strokeStyle = 'black';
context.rect(0, 0, canvas.width, canvas.height);
createRadialGradient(x2, y2, x2, y2, r);

context.stroke();
 <canvas id="myCanvas" width="500" height="500"></canvas>

答案 1 :(得分:2)

save()restore()不会影响路径对象本身的内容 - 只影响上下文的状态(包括裁剪状态)。

restore()可以删除剪辑定义,但如果路径仍然包含数据,则无论何时调用剪辑都会激活它,并且新数据会添加到路径中。

要使其正常工作,您需要确保自己正在使用干净的路径。为此,只需在使用beginPath()定义剪辑区域之前调用rect()closePath() clip()实际上没有必要clip()因为fill()(和beginPath())会因为无法使用开放路径进行剪辑而隐式关闭。

然后再进行实际绘制之前再次调用restore(),因为剪切现在是上下文状态的一部分。最后使用context.save(); // store current state to stack context.beginPath(); // clean path context.rect(x1-r,y1-r,r,r); context.clip(); // path is closed; clip is now activated context.beginPath(); // clean path for your new shape context.rect(0, 0, canvas.width, canvas.height); createRadialGradient(x1, y1, x1, y1, r); ... context.restore(); // removes the clip from state 删除剪辑定义(将状态恢复为上一个)。

var ctx = canvas.getContext('2d');

ctx.save();
ctx.beginPath();
ctx.rect(50, 50, 50, 50);
ctx.clip();

ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#900';
ctx.fill();

ctx.restore();

ctx.save();
ctx.beginPath();
ctx.rect(150, 80, 80, 60);
ctx.clip();

ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#009';
ctx.fill();

ctx.restore();

<canvas id=canvas width=500 height=180></canvas>
{{1}}