Fabricjs 文本框使文本缩小以适合

问题描述 投票:0回答:3

我会定义一个文本框(单行)

默认情况下,字符大小为16(举例)

当文本变得比文本框大时,我不希望它换行或文本框变大,我希望文本大小适合文本框的最大大小。文本。当文本恢复到较小尺寸时,它可以恢复其初始尺寸(在我们的示例 16 中)。可能管理最小尺寸

如果你有想法,我会采纳:)

提前致谢

测试用例:http://jsfiddle.net/Da7SP/273/

// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');

// ADD YOUR CODE HERE
var canvas = window._canvas = new fabric.Canvas('c');
var t1 = new fabric.Textbox('My Text', {
    width: 200,
    top: 5,
    left: 5,
    fontSize: 16,
    textAlign: 'center'
});

var t2 = new fabric.Textbox('My text is longer, but I do not want the box to grow, or the text to wrap. I only want the text to fit the available size', {
    width: 200,
    height: 200,
    top: 250,
    left: 5,
    fontSize: 16,
    textAlign: 'center'
});



canvas.add(t1);
canvas.add(t2);

一个小视频来解释我想要什么:

当文本大于文本框时,我希望文本大小适合文本框的最大大小。

javascript fabricjs
3个回答
31
投票

这是一个可以复制你的想法的基本小提琴。 要点是,您有一个在每次文本更改时触发的事件,并且可用于在渲染文本框之前执行某些操作。

在这种情况下,我根据添加到文本框中的名为

fixedWidth

的非标准参数缩小字体大小

// ADD YOUR CODE HERE
var canvas = new fabric.Canvas('c');
var t1 = new fabric.Textbox('MyText', {
    width: 150,
    top: 5,
    left: 5,
    fontSize: 16,
    textAlign: 'center',
    fixedWidth: 150
});

canvas.on('text:changed', function(opt) {
  var t1 = opt.target;
  if (t1.width > t1.fixedWidth) {
    t1.fontSize *= t1.fixedWidth / (t1.width + 1);
    t1.width = t1.fixedWidth;
  }
});

canvas.add(t1);
canvas {
    border: 1px solid #999;
}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>


3
投票

这里有一个与https://stackoverflow.com/a/41335051/1469525类似的答案,但此示例将 fontSize 修改为 maxFontSize (初始 fontSize)。这允许文本缩小然后恢复到原始大小,并防止换行。

(注意,如果你使用这个,你必须找到一种方法来阻止用户使用

enter
键。我放入了一个检查,如果检测到回车键,基本上会取消它。我的应用程序实际上有一个单独的表单来输入文本,这样我就可以通过普通的 JavaScript 来控制预防。我不太确定当画布元素可编辑时如何直接在画布元素上执行此操作,如下所示...)

var canvas = new fabric.Canvas('c');
var t1 = new fabric.Textbox('MyText', {
    width: 150,
    top: 5,
    left: 5,
    fontSize: 16,
    textAlign: 'center',
    maxFontSize: 16,
});

canvas.on('text:changed', function(opt) {
  var t1 = opt.target;
  if (t1.text.match(/[\r\n]/)) return;

  t1.set({
    fontSize: t1.maxFontSize,
  });
  while (t1._textLines.length > 1) {
    t1.set({
      fontSize: t1.fontSize - 1,
    });
  }
});

canvas.add(t1);
canvas {
    border: 1px solid #999;
}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>


0
投票

解决方案可能是创建一个新的 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;

        // If you want to enable scaling to keep writing, there are issues when you delete a portion of text and not just a single character
        //
        // this.fontSizeList = [...(this.fontSizeList || []), this.fontSize];
        // this.fontSize *= this.maxWidth / (this.width + 1);
        // this.width = this.maxWidth;
        return;
      }

      if (this._textLines.length > this.maxLines) {
        this._textBeforeEdit = oldText;
        this.hiddenTextarea.value = oldText;
        this.text = oldText;
        return;
      }
    } else {
      // If you want to enable scaling to keep writing, there are issues when you delete a portion of text and not just a single character
      //
      // const lastFontSize = this.fontSizeList?.pop();
      // if (lastFontSize) {
      //   this.fontSize = lastFontSize;
      // }

      /**
       * 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,
});
© www.soinside.com 2019 - 2024. All rights reserved.