HOY
HOY

Reputation: 1007

Prevent Fabric JS object to be visible out of the boundaries

I have 2 rectangles. When small rectangle is moved outside of the bigger rectangle, I want the small rectangle's areas outside of the boundary become invisible.

If half of small rectangle is inside and half outside. Then only half of it will be visible, this example works this way.

How can I achieve this ?

My JSFiddle

(function() {
  var canvas = this.__canvas = new fabric.Canvas('canvas');
  fabric.Object.prototype.transparentCorners = false;

  // create a rectangle with a fill and a different color stroke
  var rect = new fabric.Rect({
    left: 50,
    top: 50,
    width: 150,
    height: 250,
    fill: 'transparent',
    stroke: 'rgba(34,177,76,1)',
    strokeWidth: 1
  });

  var rect2 = new fabric.Rect({
    left: 50,
    top: 50,
    width: 50,
    height: 50,
    fill: 'rgba(34,50,100,1)',
    stroke: 'rgba(34,177,76,1)',
    strokeWidth: 1
  });
  canvas.add(rect);
  canvas.add(rect2);
})();

Example here works with this way:

Upvotes: 1

Views: 2490

Answers (1)

ɢʀᴜɴᴛ
ɢʀᴜɴᴛ

Reputation: 32879

That could be achieved in the following way, with an additional library called lodash

(function() {
    var canvas = this.__canvas = new fabric.Canvas('canvas');
    fabric.Object.prototype.transparentCorners = false;
    // create a rectangle with a fill and a different color stroke
    var rect = new fabric.Rect({
        left: 50,
        top: 50,
        width: 150,
        height: 250,
        fill: 'transparent',
        stroke: 'rgba(34,177,76,1)',
        strokeWidth: 1
    });
    var rect2 = new fabric.Rect({
        left: 50,
        top: 50,
        width: 50,
        height: 50,
        fill: 'rgba(34,50,100,1)',
        stroke: 'rgba(34,177,76,1)',
        strokeWidth: 1,
        clipName: 'rect2',
        clipTo: function(ctx) {
            return _.bind(clip, rect2)(ctx)
        }
    });

    function d2R(deg) {
        return deg * (Math.PI / 180);
    }

    function clip_name(name) {
        return _(canvas.getObjects()).where({
            clipFor: name
        }).first()
    }

    function clip(ctx) {
        this.setCoords();
        var clipObj = clip_name(this.clipName);
        var scaleXTo1 = (1 / this.scaleX);
        var scaleYTo1 = (1 / this.scaleY);
        ctx.save();
        var ctxLeft = -(this.width / 2) + clipObj.strokeWidth;
        var ctxTop = -(this.height / 2) + clipObj.strokeWidth;
        var ctxWidth = clipObj.width - clipObj.strokeWidth;
        var ctxHeight = clipObj.height - clipObj.strokeWidth;
        ctx.translate(ctxLeft, ctxTop);
        ctx.scale(scaleXTo1, scaleYTo1);
        ctx.rotate(d2R(this.angle * -1));
        ctx.beginPath();
        ctx.rect(clipObj.left - this.oCoords.tl.x, clipObj.top - this.oCoords.tl.y, clipObj.width, clipObj.height);
        ctx.closePath();
        ctx.restore();
    }
    rect.set({
        clipFor: 'rect2'
    });
    canvas.add(rect);
    canvas.add(rect2);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.9/fabric.min.js"></script>
<canvas id="canvas" width="800" height="600"></canvas>

Upvotes: 3

Related Questions