1

I have an issue with globalCompositeOperation.

My goal is to make Blue element displayed only inside of Red element and should not be visible outside of Red rectangle at all (kind of Overflow-Hidden effect). Plus, both Red and Blue must have Transformation ability (both editable).

As you can see, if I'll add one more element into the canvas (yellow element), the Blue one become visible on the area where Yellow and Blue overlaps.

http://jsfiddle.net/redlive/q4bvu0tb/1/

var canvas = new fabric.Canvas('c');


var yellow = new fabric.Circle({
  top: 200,
  left: 0,
  radius: 100,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'yellow'
});
canvas.add(yellow);


var red = new fabric.Rect({
  top: 0,
  left: 0,
  width: 300,
  height: 300,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'red',
  rx: 40
});
canvas.add(red);


var blue = new fabric.Circle({
  top: 150,
  left: 80,
  radius: 100,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'blue',
    globalCompositeOperation: 'source-atop'
});
canvas.add(blue);



var green = new fabric.Circle({
  top: 0,
  left: 0,
  radius: 100,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'green'
});
canvas.add(green);

Mandatory Conditions:

  • Preserve elements appearance on Canvas.
  • No clipping (since clipping does not allow to add background color and image in the same time)
Eugene Vilder
  • 492
  • 1
  • 9
  • 26

1 Answers1

3

It could be accomplish-able using the following steps ...

  • remove the yellow element before drawing the blue one
  • after drawing the blue element set the yellow element's globalCompositeOperation to destination-over and add it back

var canvas = new fabric.Canvas('c');

var yellow = new fabric.Circle({
  top: 200,
  left: 0,
  radius: 100,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'yellow'
});
canvas.add(yellow);

var red = new fabric.Rect({
  top: 0,
  left: 0,
  width: 300,
  height: 300,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'red',
  rx: 40
});
canvas.add(red);

canvas.remove(yellow); //remove yellow

var blue = new fabric.Circle({
  top: 150,
  left: 80,
  radius: 100,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'blue',
  globalCompositeOperation: 'source-atop'
});
canvas.add(blue);

yellow.set({globalCompositeOperation: 'destination-over'}); //set gCO for yellow
canvas.add(yellow); //add yellow back

var green = new fabric.Circle({
  top: 0,
  left: 0,
  radius: 100,
  strokeDashArray: [5, 5],
  stroke: 'black',
  strokeWidth: 5,
  fill: 'green'
});
canvas.add(green);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id="c" width="800" height="800"></canvas>
ɢʀᴜɴᴛ
  • 32,025
  • 15
  • 116
  • 110
  • Thank you for your comment... In this way it will, I know... The problem is that elements load dynamically to the canvas and I need to preserve they appearance (z-index). Yellow must be behind the Red area. – Eugene Vilder Apr 17 '17 at 17:14
  • Very nice... could be a potential solution, however, that kind of manipulation with Removing and Adding elements breaks the condition of dynamic elements' rendering and, as a consequence, won't preserve their ordering... – Eugene Vilder Apr 17 '17 at 18:53
  • Well.. after playing with "dynamic" rendering, I've realized that Removing elements and bring them back isn't a good idea because you never know what is an upcoming element and what element needs to be removed and then brought back... anyways... – Eugene Vilder Apr 17 '17 at 23:29
  • Does this work when we add objects dynamically? – Raghavendra Reddy Jul 20 '22 at 10:15