标题说明了所有。当fabric.IText
成为fabric.Group
的一部分时,它不再像可编辑的文字那样做出反应。
以下是一个用例:http://jsfiddle.net/vAjYd/
有没有办法解决这个问题?否则我必须写上我的小组。
顺便说一下:fabric.Group
有许多优点,但是禁用事件使得无法用于UI元素(即这个用例或按钮组作为文本和组的组)。
答案 0 :(得分:18)
我可能来不及回答这个问题,但肯定很多人喜欢我搜索这个答案应该符合解决方案。 你可以找到一个完美的iText解决方案,用户可以编辑iText的文本,这是fabric.group的一部分。 Working solution
此处遵循的方法是:
用户退出编辑模式后,元素将再次组合在一起。
// 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();
}));
});
答案 1 :(得分:0)
目前,IText无法处理这些事件,因为如果它们包含在一个组中,它们就不会传递给它。我认为这也是处理它的首选方式,因为它会让用户感到困惑 - 如果他开始编辑多个文本会怎样。这可能最终会变得一团糟。也许你可以稍微修改你的脚本来解决这个问题。
答案 2 :(得分:0)
感谢您的回答,但是不能确保只重新组合组中的项目,我们必须将“ canvas.forEachObject ”更改为“ groupItems ”因为它会尝试将画布中的所有项目仅放回属于该组的所有项目。请参阅以下代码
// 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();
}));
});
答案 3 :(得分:0)
如果您希望为itext提供真实的视觉填充(如css),则可以在itext后面添加一个不可选择的Rect。并根据所有事件(例如移动,缩放等)调整Rect位置。
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 ));
};
答案 4 :(得分:0)
我知道为时已晚,但这是您遇到的问题的有效代码: http://jsfiddle.net/fd4yrxq6/2/
我刚刚使用上述软件做了一些小改动:
...
// 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();
}));
});
...
答案 5 :(得分:0)
我是最后一个答案,但更好的答案, 一个 gif 演示价值一千个字
如您所见,效果很好,链接地址 https://jsfiddle.net/hejie/rhf069ob/latest
解决方案:
textbox inside group
textbox inside group
相同textbox inside group
,并删除临时文本框为什么这个解决方案比 group/ungroup
更好?
简而言之,不要使用分组/取消分组的解决方案! 尝试以下代码:
var canvas = new fabric.Canvas('canvas');
canvas.setWidth(300);
canvas.setHeight(300);
function createGroup() {
let circle = new fabric.Circle({
radius:40,
fill: 'rgba(200, 0, 0, 0.3)',
originX: 'center',
originY: 'center',
});
let text = new fabric.Textbox("AJLoveChina", {
originX: 'center',
originY: 'center',
textAlign: 'center',
fontSize: 12,
})
let group = new fabric.Group([circle, text], {
left: 100,
top: 100,
originX: 'center',
originY: 'center',
});
group.on('mousedblclick', () => {
// textForEditing is temporary obj,
// and will be removed after editing
let textForEditing = new fabric.Textbox(text.text, {
originX: 'center',
originY: 'center',
textAlign: text.textAlign,
fontSize: text.fontSize,
left: group.left,
top: group.top,
})
// hide group inside text
text.visible = false;
// note important, text cannot be hidden without this
group.addWithUpdate();
textForEditing.visible = true;
// do not give controls, do not allow move/resize/rotation on this
textForEditing.hasConstrols = false;
// now add this temporary obj to canvas
canvas.add(textForEditing);
canvas.setActiveObject(textForEditing);
// make the cursor showing
textForEditing.enterEditing();
textForEditing.selectAll();
// editing:exited means you click outside of the textForEditing
textForEditing.on('editing:exited', () =>{
let newVal = textForEditing.text;
let oldVal = text.text;
// then we check if text is changed
if (newVal !== oldVal) {
text.set({
text: newVal,
visible: true,
})
// comment before, you must call this
group.addWithUpdate();
// we do not need textForEditing anymore
textForEditing.visible = false;
canvas.remove(textForEditing);
// optional, buf for better user experience
canvas.setActiveObject(group);
}
})
})
canvas.add(group);
}
createGroup();
#canvas {
width:300px;
height:300px;
border: 1px solid #333;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.4.0/fabric.min.js"></script>
<h4>fabricjs editing textbox inside fabric Group</h4>
<canvas id="canvas"></canvas>