alexrogers
alexrogers

Reputation: 1584

More than one clip call per context in canvas

I cannot seem to get a second clip call working in canvas. See fiddle: http://jsfiddle.net/m2hL17nu/ Notice how the first radial grad is clipped but the second isn't.

I have seen Can you have multiple clipping regions in an HTML Canvas? but save restore still doesn't seem to be letting the next clip() work.

Thanks in advance for your help. See code below:

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();

Upvotes: 0

Views: 993

Answers (2)

NullPointer
NullPointer

Reputation: 159

you should use beginPath() and closePath() before drawing the clips and after the clip() methods respectively:

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>

Upvotes: 5

user1693593
user1693593

Reputation:

The save() and restore() does not affect the content of the path object itself - only the state of the context (which includes clipping state).

restore() can remove the clip definition but if the path still contains data it will be activated next time you call clip regardless, together with new data added to the path.

To make it work you need to make sure you're working with a clean path. For that simply call beginPath() before defining the clip area with rect(). closePath() is really not necessary with clip() as clip() (and fill()) will close implicit due to it being impossible to clip with an open path.

Then before doing actual drawing call beginPath() again as clipping is now a part of the context state. Finally use restore() to remove the clipping definition (revert state to previous).

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>

Upvotes: 2

Related Questions