Serks
Serks

Reputation: 333

Select and manipulate particular paths within a path group fabric.js

I am making an app that involves shapes like cylinders and boxes, and need to be able to do this with fabric.js. I know about three.js but for my purposes, it must be in 2D.

Initially I thought I would just create them in 3D software and render images which can then be added to the canvas, which I did successfully...

enter image description here

However, I have run into a hurdle where fabric only allows patterns to be filled onto paths or objects (rect, circle etc.)....not images (png).

Since I absolutely need patterns, I now need to create these cylinders in SVG. I have gotten as far as making the cylinders in Illustrator, saving them as SVG's and then using them on the canvas, then adding fill patterns on them. So far so good.

Now I want to be able to fill a different pattern for the top of the cylinder, and a different pattern to the side BUT still have it as one object.

So...How can I select and manipulate particular paths within a path group? Is there anyway to give each path within the group a custom attribute (eg. name) which I can then target? Do I need to create two seperate SVG files and then add them seperately, and if so, how can I do this and still have it as one object?

Here's how I am adding the svg to the canvas...

fabric.loadSVGFromURL("/shapes/50-250R.png", function(objects) {
  var oImg = fabric.util.groupSVGElements(objects);

  oImg.perPixelTargetFind = true;
  oImg.targetFindTolerance = 4;
  oImg.componentType = "Shape";
  oImg.lockUniScaling = true;
  oImg.lockScalingX = true;
  oImg.lockScalingY = true;
  oImg.setControlsVisibility({'tl': false, 'tr': false, 'bl': false, 'br': false});

  canvas.add(oImg);
  canvas.renderAll();
});

Here is how I am adding the pattern...

var textureIMG = new Image;
textureIMG.crossOrigin = "anonymous"; 
textureIMG.src = texture.image;

obj.setFill(); //For some reason, the fill doesn't happen without this line.

var pattern = new fabric.Pattern({
  source: textureIMG,
  repeat: 'repeat'
});

if (obj instanceof fabric.PathGroup) {
  obj.getObjects().forEach(function(o) {
    o.setFill(pattern);
  });
} else {
  obj.setFill(pattern);
}

canvas.renderAll();

Thanks in advance.

Upvotes: 0

Views: 1379

Answers (1)

Serks
Serks

Reputation: 333

So I managed to figure this out. Each path within the path group is stored in the 'paths' array of the object.

I can now add a pattern to the top of the cylinder using...

var obj = canvas.getActiveObject();
obj.paths[0].fill = patternOne;

and to the sides using...

obj.paths[1].fill = patternTwo;

enter image description here

Upvotes: 2

Related Questions