Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FabricJS prevent canvas.clipTo from clipping canvas.backgroundImage

I want to set a global clipTo in my Fabric-powered Canvas that will affect all user-added layers. I want a background image and an overlay image, which are unaffected by this clip mask.

Example:

enter image description here

Here's what's happening in this photo:

  1. A canvas overlay image makes the t-shirt look naturally wrinkled. This overlay image is mostly transparent
  2. A background image in the exact shape of the t-shirt was added, which is supposed to make the t-shirt look blue
  3. A canvas.clipTo function was added, which clips the canvas to a rectangular shape
  4. A user-added image (the famous Fabric pug) was added

I want the user-added image (the pug) to be limited to the rectangular area.

I do not want the background image (the blue t-shirt shape) affected by the clip area.

Is there a simple way to accomplish this? I really don't want to have to add a clipTo on every single user layer rather than one tidy global clipTo.

You can play with a JS fiddle showing the problem here.

like image 477
chadoh Avatar asked Oct 07 '15 15:10

chadoh


1 Answers

I came here with the same need and ultimately found a solution for what I'm working on. Maybe it helps:

For SVG paths, within the clipTo function you can modify the ctx directly prior to calling render(ctx) and these changes apply outside the clipped path o. Like so:

var clipPath = new fabric.Path("M 10 10 L 100 10 L 100 100 L 10 100", {
  fill: 'rgba(0,0,0,0)',
});

var backgroundColor = "rgba(0,0,0, 0.2)";

var opts = {
  controlsAboveOverlay: true,
  backgroundColor: 'rgb(255,255,255)',
  clipTo: function (ctx) {
    if (typeof backgroundColor !== 'undefined') {
      ctx.fillStyle = backgroundColor;
      ctx.fillRect(0, 0, 300, 150);
    }
    clipPath.render(ctx);
  }
}
var canvas = new fabric.Canvas('c', opts);

canvas.add(new fabric.Rect({
  width: 50,
  height: 50,
  left: 30,
  top: 30,
  fill: 'rgb(255,0,0)'
}));

You can of course add an image instead of a color, or whatever else you want done. The trick I've found is to put it in the clipTo function on the ctx directly.

here's a fiddle

like image 151
Kyle Shike Avatar answered Oct 22 '22 06:10

Kyle Shike