调整 fabricjs 文本框大小以匹配文本选择

Adjust fabricjs text box size to match the text selection

我有一段代码可以这样创建一个新的 Textbox

new fabric.Textbox('Ajouter du texte')

问题是文本框与其内容相比太小了:

如果我设置固定宽度,我会得到一些填充:

new fabric.Textbox('Ajouter du texte', {width: 350})

如何调整文本框大小以匹配文本选择大小?我找不到有关如何获取选择尺寸的任何信息。

我正在使用结构版本 4.0.0-beta.5

我在 TextBox 文档中进行了搜索,但没有找到任何可以根据文本大小自动调整容器的内容。

你能做的最好的事情是获取每行的大小,如果宽度总和小于最大所需值,则将宽度设置为文本框。出于某种原因,您还需要为其添加一个小宽度。

var canvas = new fabric.Canvas("canvas");
var text = new fabric.Textbox("Ajouter du texte");

var textSize = 0;
for (var i = 0; i < text._textLines.length; i++) {
  textSize += text.measureLine(i).width;
}

var augmentedTextSize = textSize + 25;
if (augmentedTextSize < 500) {
  text.set({ width: augmentedTextSize });
}

canvas.add(text);
canvas.renderAll();

检查这个例子:https://codesandbox.io/s/Whosebug-60411035-fabric-js-400-beta5-7s7id

如果文本框上有某种 属性 会很好,例如 "max_width",如果文本小于它,则自动调整大小以适应文本大小。

我现在保留的解决方案是逐渐增加宽度,直到不超过 1 行:

const text = new fabric.Textbox("Ajouter du texte")

while (text.textLines.length > 1) {
  text.set({width: text.getScaledWidth() + 1})
}

欢迎提出更好的解决方案,以便我更新已接受的答案。

[编辑]

要使其在文本编辑期间工作:

function adjustTextWidth(evt: fabric.IEvent) {
  if (evt.target instanceof fabric.IText) {
    const text = evt.target.text || ""
    while (evt.target.textLines.length > text.split("\n").length) {
      evt.target.set({width: evt.target.getScaledWidth() + 1})
    }
  }
}

canvas.on("text:changed", adjustTextWidth)

[EDIT2]

我找到了实现目标的更好方法:

fabric.Textbox.prototype._wordJoiners = /[]/;

这样,space 就不会被视为单词连接符,只有当用户键入 Enter 时,文本才会中断。我还添加了这个功能来在删除文本时调整文本框的宽度:

function fitTextboxToContent(text: fabric.IText) {
  const textLinesMaxWidth = text.textLines.reduce((max, _, i) => Math.max(max, text.getLineWidth(i)), 0);
  text.set({width: textLinesMaxWidth});
}