FabricJS ClipTo Issue for multiple objects like group
Asked Answered
A

2

1

My code is

canvas.clipTo = function (ctx) {

    ctx.beginPath();
    for (var i = 0; i < totalPrintArea; i++) {
        ctx.save();
        ctx.fillStyle = 'rgba(51,51,51,0)';
        ctx.rect(clipLft[i], clipTp[i], clipW[i], clipH[i], 'rgba(51,51,51,1)', clipRtn[i]);
        ctx.stroke();
        ctx.restore();
    }

    ctx.closePath();
    ctx.clip();
    canvas.calcOffset();
};
canvas.renderAll();

I am taking values from the red dotted box and apply to clip where multiple masks are generating.

My issue is its taking all properties but not rotation for all.

I want to rotate all the rectangles.

I just get some code to change the rotation for the clip like ctx.rotate(50); but will not work as I want to make all rotate with their own values

Please guide me for the same.

no description

Applewhite answered 24/4, 2014 at 8:51 Comment(3)
Please check below specific code for the same object.clipTo = function (ctx) { ctx.rect (x, y, width, height); } I want to add rotation property for rectangle and not to the ctx like ctx.rotate(50) not work for me i want like ctx.rect (x, y, width, height, rotate);Applewhite
Please guide me for the sameApplewhite
You could take a look at the answer on this question, there is a method to convert the angle #16438196Apodaca
S
0

On the original fabricJS github project I saw the comment: https://github.com/kangax/fabric.js/issues/932#issuecomment-27223912

and decided that I need to prevent making ctx.beginPath all the time:

canvas.clipTo = function(ctx) { 
var skip = false;
// Workaround to make possible 
// making clipTo with 
// fabric.Group 
var oldBeginPath = ctx.beginPath;
ctx.beginPath = function() {
if (!skip) {
  oldBeginPath.apply(this, arguments);
  skip = true;
  setTimeout(function() {
    skip = false;
  }, 0);
}
}
group.render(ctx)
};

You can see my workaround to the problem described: https://jsfiddle.net/freelast/6o0o07p7/

The workaround is not perfect, but hope it will help somebody.

Selfrighteous answered 4/7, 2016 at 15:18 Comment(0)
F
0

I have tried using the Andrey's answer, but althouth there some interesting points, it didn't work.

If you try to clip the canvas to a single object (e.g. a circle or a rectangle), you can simply do this:

canvas.clipTo = function(ctx) {
    shape.render(ctx); //shape is a circle, for instance
}

However, as explained by Kienz and butch2k in the aforementioned comment on GitHub, the problem is that you cannot use this solution with groups. In particular, if you use the following snippet:

canvas.clipTo = function(ctx) {
    group.render(ctx);
}

you will only see one object of the group to be used for clipping.

The issue is due to the render method, which calls the ctx.beginPath() and ctx.closePath() for each object in the group. And because only the last couple of beginPath-closePath calls will affect the clipping, you need some workaround.

So in my solution, I have temporarily redefined the ctx.closePath and ctx.beginPath methods (after storing them in other two temporary variables, named oldBeginPath and oldClosePath) so that they do nothing. Then I call oldBeginPath at the beginning, and after rendering all the objects in the group I call the oldClosePath.

And now, here is the (working) snippet:

canvas.clipTo = function(ctx) {
    var oldBeginPath = ctx.beginPath;
    var oldClosePath = ctx.closePath;

    ctx.beginPath = function() {}
    ctx.closePath = function() {}

    oldBeginPath.apply(ctx);
    group.forEachObject(function(shape){
        shape.render(ctx);
    });
    oldClosePath.apply(ctx);

    ctx.beginPath = oldBeginPath;
    ctx.closePath = oldClosePath;
};

Hope this will save someone's spare time in the future.

Fernanda answered 28/8, 2016 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.