Fabric.js - Grouped iText Not Editable

The name says it all. When fabric.IText is part of fabric.Group , it no longer responds as editable text.

Here is a usage example: http://jsfiddle.net/vAjYd/

Is there any way to solve this problem? Otherwise, I have to write my group.

Btw: A fabric.Group has many advantages, but a disabled event makes it impossible to use for UI elements (i.e. this use case or button groups in the form of groups of texts and rectangles).

+9
fabricjs
source share
5 answers

Currently, IText cannot process events because they are not passed to it if they are contained in a group. I think this is also the preferred way to handle this, as it will confuse the user - what if he starts editing several texts. It may end in a mess. Perhaps you can rework your script a bit to get around these problems.

0
source share

I may be late to answer this, but surely many of you, like me, looking for this answer, should answer this decision. You can find a perfectly working iText solution where the user can edit the iText text, which is part of fabric.group. Working solution

The following is the approach:

  • When the user double-clicks the desired group, we ungroup all the elements
  • set focus on an iText element
  • Enters iText editing mode and selects all the text so that the user can directly start editing.
  • When the user exits edit mode, the elements are again grouped together.

     // ungroup objects in group var items var ungroup = function (group) { items = group._objects; group._restoreObjectsState(); canvas.remove(group); for (var i = 0; i < items.length; i++) { canvas.add(items[i]); } // if you have disabled render on addition canvas.renderAll(); }; // Re-group when text editing finishes var dimensionText = new fabric.IText("Dimension Text", { fontFamily: 'Comic Sans', fontSize: 14, stroke: '#000', strokeWidth: 1, fill: "#000", left: 170, top: 60 }); dimensionText.on('editing:exited', function () { var items = []; canvas.forEachObject(function (obj) { items.push(obj); canvas.remove(obj); }); var grp = new fabric.Group(items.reverse(), {}); canvas.add(grp); grp.on('mousedown', fabricDblClick(grp, function (obj) { ungroup(grp); canvas.setActiveObject(dimensionText); dimensionText.enterEditing(); dimensionText.selectAll(); })); }); 
+18
source share

Thanks for the answer. However, it does not guarantee the regrouping of only the elements in the group, we must change the ' canvas.forEachObject ' to groupItems since it will try to return all the elements on the canvas only those that belong to the group. See the following code

 // ungroup objects in group var groupItems = [] var ungroup = function (group) { groupItems = group._objects; group._restoreObjectsState(); canvas.remove(group); for (var i = 0; i < groupItems.length; i++) { canvas.add(groupItems[i]); } // if you have disabled render on addition canvas.renderAll(); }; // Re-group when text editing finishes var dimensionText = new fabric.IText("Dimension Text", { fontFamily: 'Comic Sans', fontSize: 14, stroke: '#000', strokeWidth: 1, fill: "#000", left: 170, top: 60 }); dimensionText.on('editing:exited', function () { var items = []; groupItems.forEach(function (obj) { items.push(obj); canvas.remove(obj); }); var grp = new fabric.Group(items.reverse(), {}); canvas.add(grp); grp.on('mousedown', fabricDblClick(grp, function (obj) { ungroup(grp); canvas.setActiveObject(dimensionText); dimensionText.enterEditing(); dimensionText.selectAll(); })); }); 
0
source share

If you need real visual indentation (e.g. css) for itext, you can add a non-selectable Rect right after the itext. And adjust the position of the Rect based on all events for the itext, like moving, scaling, etc.

 self.createITextWithPadding = function (event) { var itext = new fabric.IText('Done', { fontSize: 18, padding : tnbConstants.ITEXT.PADDING, fill: '#FFF', }); itext.left = (event.pageX - $("#tnb-panel").position().left)-itext.width/2; itext.top = (event.pageY-$("#tnb-panel").position().top)-itext.height/2; var bg = new fabric.Rect({ fill: '#32b775', left : itext.left - tnbConstants.ITEXT.PADDING, top :itext.top - tnbConstants.ITEXT.PADDING, rx: 5, ry: 5, width: itext.width + tnbConstants.ITEXT.PADDING*2, height:itext.height + tnbConstants.ITEXT.PADDING*2, selectable : false }); itext.bgRect = bg; itext.on("moving",self.adjustBackRect); itext.on("scaling",self.adjustBackRect); return itext; } self.adjustBackRect = function (e) {//e is event var text = e.target; var bgRect = text.bgRect; bgRect.set({ left : text.left - text.padding, top : text.top - text.padding, width : text.width * text.scaleX + text.padding * 2, height : text.height * text.scaleY + text.padding * 2 , }); console.log("text width :" + (text.width * text.scaleX + text.padding*2)); console.log("text height :" + (text.height * text.scaleY + text.padding*2)); console.log("bg width :" + (bgRect.width )); console.log("bg height :" + (bgRect.height )); }; 
0
source share

I know it's too late, but here is the working code for your problem: http://jsfiddle.net/fd4yrxq6/2/

I just made small changes using the above accidents:

 ... // ungroup objects in group var items; var ungroup = function (group) { items = group._objects; group._restoreObjectsState(); canvas.remove(group); canvas.renderAll(); for (var i = 0; i < items.length; i++) { canvas.add(items[i]); } // if you have disabled render on addition canvas.renderAll(); }; ... dimensionText.on('editing:exited', function () { for (var i = 0; i < items.length; i++) { canvas.remove(items[i]); } var grp = new fabric.Group(items, {}); canvas.add(grp); grp.on('mousedown', fabricDblClick(grp, function (obj) { ungroup(grp); canvas.setActiveObject(dimensionText); dimensionText.enterEditing(); dimensionText.selectAll(); })); }); ... 
0
source share

All Articles