Search code examples
javascripttypescriptfabricjs

Adjust fabricjs text box size to match the text selection


I have a piece of code that creates a new Textbox this way:

new fabric.Textbox('Ajouter du texte')

The problem is the text box is to small compare to its content:

enter image description here

If I set a fixed width, I get some padding around:

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

screenshot

How can I adjust the text box size to match the text selection size? I can't find anything about how to get the selection dimensions.

I'm using fabric version 4.0.0-beta.5.


Solution

  • The solution I keep for now is to increase the width gradually till I get no more than 1 line:

    const text = new fabric.Textbox("Ajouter du texte")
    
    while (text.textLines.length > 1) {
      text.set({width: text.getScaledWidth() + 1})
    }
    

    Feel free to propose a better solution, so I can update the accepted answer.

    [EDIT]

    To make it work during text edition:

    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)
    

    enter image description here

    [EDIT2]

    I found a better way to achieve my goal:

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

    This way, the space is not considered a word joiner and the text breaks only when the user types Enter. I also added this function to adjust the textbox width when text is removed:

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