Reputation: 1066
Fabric.js does not support editing text objects when they are within a group. How can one achieve this feature?
Upvotes: 1
Views: 3193
Reputation: 1066
The solution is based on ungrouping the group of objects while maintaining their state, adding the subTargetCheck:true
option as true
to fabric.Group
objects that contain text you'd like to edit.
The ungrouping is achieved on a simulated double click event using a mousedown
listener on the top level group of objects. A mousedown
listener is also added to the text objects within the group.
Once the text is edited, the objects are regrouped by removing original objects and replacing them with a new group with the same properties on the 'editing:exited' event returned by fabric.js
.
const canvas = new fabric.Canvas("canvas");
canvas.setWidth(350);
canvas.setHeight(350);
// Double-click event handler
const fabricDblClick = function(obj, handler) {
return function() {
if (obj.clicked) handler(obj);
else {
obj.clicked = true;
setTimeout(function() {
obj.clicked = false;
}, 500);
}
};
};
// ungroup objects in group
let groupItems = [];
let ungroup = function(group) {
groupItems = group._objects;
group._restoreObjectsState();
canvas.remove(group);
for (var i = 0; i < groupItems.length; i++) {
canvas.add(groupItems[i]);
}
canvas.renderAll();
};
// Re-group when text editing finishes
const firstText = new fabric.IText("First Text", {
fontFamily: "Comic Sans",
fontSize: 14,
stroke: "#000",
strokeWidth: 1,
fill: "#000",
left: 170,
top: 60
});
const secondText = new fabric.IText("Second Text", {
fontFamily: "Comic Sans",
fontSize: 14,
stroke: "#000",
strokeWidth: 1,
fill: "#000",
left: 170,
top: 80
});
firstText.on("editing:exited", () => {
var items = [];
groupItems.forEach(function(obj) {
items.push(obj);
canvas.remove(obj);
});
const newTextGroup = new fabric.Group(items.reverse(), {
subTargetCheck: true
});
canvas.add(newTextGroup);
newTextGroup.on(
"mousedown",
fabricDblClick(newTextGroup, obj => {
ungroup(newTextGroup);
})
);
});
let addGroup = () => {
const textGroup = new fabric.Group([secondText, firstText], {
left: 50,
top: 50,
subTargetCheck: true
});
canvas.add(textGroup);
textGroup.on(
"mousedown",
fabricDblClick(textGroup, obj => {
if (isTextGroup(obj)) {
obj.getObjects().forEach(item => {
item.on("mousedown", e => {
if (e.target.type === "i-text") {
e.target.enterEditing();
e.target.hiddenTextarea.focus();
}
});
});
}
ungroup(textGroup);
})
);
};
addGroup();
let isTextGroup = object => {
return object.getObjects().every(el => {
return el.type === "i-text";
});
};
.canvas {
width: 350px;
height: 350px;
border: 1px solid Black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.6.0/fabric.min.js"></script>
<canvas id="canvas" class="canvas" ></canvas>
Upvotes: 1