我正在尝试使用 IText 或 Textbox 对象在织物画布上创建文本输入。这似乎在使用 Fabric 的 http://impretty.me 上完成得很好,但我似乎无法复制他们在这里所做的事情。我希望能够在 IText 上设置最大宽度/最大字符数,或者将 Textbox 对象限制为单行。
我的问题是在 IText 上设置宽度是无效的,即使宽度参数在 Textbox 上有效,我也需要将文本保持为单行。缩放文本(如 http://impretty.me 所示)会很好,但不是必需的。任何帮助将不胜感激。
我此时已经制定出的文本框和交互的代码如下。
const text = new fabric.IText('Type Your Message', {
originY: 'center',
hoverCursor: 'text',
left: 210,
top: 825,
width: 300,
fontFamily: 'Permanent Marker',
fontSize: 50,
hasBorders: false,
hasControls: false,
lockMovementX: true,
lockMovementY: true,
id: 'text'
})
canvas.add(text)
text.on('changed', function (options) {
if (this.width >= 635) {
const newText = this.text.slice(0, -1)
this.text = newText
this.hiddenTextarea.value = newText
console.log(this)
}
})
您可以调整文本大小以适合边界框
sizeDownTextNew = function(canvasObj, limit_height, limit_width )
{
if(typeof (canvasObj) == "undefined" || canvasObj == null)
return;
var counter = 250; //Maximum of 250iterations to size down
var initial_height = limit_height;
var max = canvasObj.get('fontSize');
var min = 6; //This is our minimum size
var foundmin=0; //Flag if minimum is met
var ratio = max;
//Now reduce the size of actual text font size property
while(canvasObj.height+2<canvasObj._getTextHeight()) //While the height of text is larger then actual text, try reducing the lineHeight
{
var fontSize = parseFloat(canvasObj.get('fontSize'));
fontSize=fontSize - fontSize/max; //reduce the size with a set ratio
if(fontSize > min) //If main font is greater then min font, we will now reduce
{
canvasObj.set('fontSize', fontSize);
canvasObj.height = initial_height
canvasObj.canvas.renderAll();
canvasObj.height = initial_height;
canvasObj.setCoords();
canvasObj.canvas.renderAll();
if(counter == 0) //Failsafe to exit the while loop if no condition is met
break;
}
counter = 300;
while(limit_width<canvasObj._getTextWidth()) //While the width of text is larger then actual text, try reducing it
{
var fontSize = parseFloat(canvasObj.get('fontSize'));
fontSize=fontSize - fontSize/ratio; //reduce the size with a set ratio
canvasObj.setCoords();
canvasObj.canvas.renderAll();
}
else
{
break;
}
canvasObj.width = limit_width;
counter -- ;
if(counter == 0)
{
break;
}
}
}
然后像这样调用这个函数
text.on('changed', function (options) {
sizeDownTextNew(这个,500,60); })
您可以将“maxLength”添加到文本区域。
this.on("editing:entered", () => {
if (this.hiddenTextarea) {
// limit textarea length
this.hiddenTextarea.maxLength = 40;
}
});
要限制 Fabric js 版本 2+ 的文本, 我们需要重写 onInput 函数,如下
onInput: function(e) {
if(this.width > this.maxWidth) {
return;
}
if(this._textLines.length > this.maxLines) {
return;
}
// Call parent class method
this.callSuper('onInput', e);
}
注意:maxWidth - 限制宽度
和 maxLines - 限制文本框中的高度/行。
编辑:固定语法。
解决方案可能是创建一个新的 Fabric 类来扩展 Fabric.Textbox 类。这是一个例子:
const LimitedTextbox = fabric.util.createClass(fabric.Textbox, {
onInput: function (e: any) {
const oldText = this.text;
/**
* Sometimes, when you insert a line break, it doesn't appear to Fabric as an 'insertLineBreak' but simply sets the date to null.
* Therefore, it's important to check that it's not deleting any characters, and if the date is null, it means that a new line is being inserted
*/
if (e.inputType === 'insertLineBreak' || (e.inputType !== 'deleteContentBackward' && !e.data)) {
this._textBeforeEdit = oldText;
this.hiddenTextarea.value = oldText;
this.text = oldText;
return;
} else if (e.inputType !== 'deleteContentBackward') {
if (this.width > this.maxWidth) {
this._textBeforeEdit = oldText;
this.hiddenTextarea.value = oldText;
this.text = oldText;
return;
}
if (this._textLines.length > this.maxLines) {
this._textBeforeEdit = oldText;
this.hiddenTextarea.value = oldText;
this.text = oldText;
return;
}
} else {
/**
* It's needed because otherwise, if I write many characters, he automatically adjusts the width even if the visible text doesn't change.
* So, every time I delete something, I reset the width.
* I do it during deletion; otherwise, if I do it in the maxWidth check, I never block it, and it would keep writing
*/
this.width = this.maxWidth;
}
this.callSuper('onInput', e);
},
});
...
textbox = new LimitedTextbox('custom text', {
maxLines: 1,
maxWidth: 100,
});