Reputation: 1090
I am calling a tag, a colored rectangle with an editable text on it. I dont want the Text become deformed, it must keep letter width and wraps lines if too small. The text should be centered in the rectangle.
To do it, I need to create a subclass of Fabric Object, it appears i have 2 solutions:
Use a LabeledRect like in tutorials, this is a Rect with a Text in attribute.
Use a group with a Rect and a Textbox. But this is a group and i don't find any working solution to edit text while Textbox is in group. See fiddle.
fabric.Tag = fabric.util.createClass(fabric.Group, {
type: 'ce.tag',
initialize: function() {
options = {};
options.top = 10;
options.left = 10;
var defaults = {
width: 300,
height: 30,
originX: 'center',
originY: 'center'
};
var items = [];
items[0] = new fabric.Rect($.extend({}, defaults, {
fill: '#77AAFF',
}));
items[1] = new fabric.Textbox('Nouvelle étiquette', $.extend({}, defaults, {
textAlign: 'center',
fontSize: 20
}));
this.callSuper('initialize', items, options);
},
});
canvas.add(new fabric.Tag())
The problem with option #2 (and probably #1) is the text should be editable and this is not.
I currently have some rendering issue with option #2, when unserializing, the fill property is reset to default (black). See fiddle In fact, this is the Group's default and FabricJS applies delegated properties to objects. Juste set "delegatedProperties: {}" into the Tag declaration and no property is delegated.
NOTE: Using a group is not a good idea, there is many properties in many way there are delegated or share between group and its children.
Upvotes: 1
Views: 4931
Reputation: 3542
I'm struggling with the same issue. From my research into it so far, I see two options to build on to each of your two paths:
1) Create an extended class, as you suggest via LabeledRect. BUT, instead of extending the Rectangle class - extend the IText (or Textbox) class with rectangle drawing functions. The ctx logic that draws the rectangle shouldn't be too hard to port into the IText class, and that way we can get all the nice methods provided by IText for editablity.
You can see the _render rectangle code in line 14,553 in version 1.6.0-rc.1
2) As you note you lose editability when you group things. A previous question posted a working fiddle showing code to ungroup/regroup when selecting items. This allows the user to access the IText functionality, and then when done editing re-group puts it all back together again.
All the other questions I found about this pointed back to this answer.
Problems with this method: first, the original poster's code works but only on his specific use case - it will need to be generalized (and ideally could be set up as a service). Second, I tested adding additional objects to the canvas in that example, and during re-group all objects get added to the group (including ones not in the original group).
If you decide to go this route, I think you'll need to: a) Make it into a service, so it can be called on any object in the canvas b) Come up with some way to limit the re-grouping to only the objects you want.
You should be able to do b) by either using intersections to group only the objects that the IText is touching (see Intersections example here) or use some custom tag element to your objects to know what group they should belong to (for instance, create a custom "group-id" attribute to a custom subclass of fabric.rect, the same way you'd make a custom subclass in the LabeledRect tutorial).
I'll follow up if I'm able to implement any of these (but I'm just starting in Fabric/Javascript so I might not be able to).
Upvotes: 2