Modify the size of the fabricjs text box to perfectly match the chosen text

I'm currently facing an issue with my code snippet that is supposed to create a new Textbox:

new fabric.Textbox('Add some text')

The problem I'm encountering is that the text box appears too small compared to its content:

https://i.sstatic.net/koqcs.png

If I try setting a fixed width, then I end up with unwanted padding around the text:

new fabric.Textbox('Add some text', {width: 350})

https://i.sstatic.net/NYzX1.png

Is there a way for me to adjust the size of the text box to match the text selection size? I've tried looking for information on how to obtain the selection dimensions but haven't found anything useful so far.

The version of fabric I'm using is 4.0.0-beta.5.

Answer №1

One approach I'm currently using is to gradually increase the width until the text fits on just one line:

const text = new fabric.Textbox("Add some text")

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

If you have a better solution, feel free to suggest it so that I can update the accepted answer.

[EDIT]

To adjust the text width during text editing:

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)

https://i.sstatic.net/CDCtW.gif

[EDIT2]

I came across a more efficient method to achieve my objective:

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

This configuration ensures that spaces are not considered word joiners and text only breaks when the user presses Enter. Additionally, I included a function to adjust the textbox width when text is deleted:

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

Answer №2

In my quest for information regarding the TextBox feature, I was unable to find any built-in functionality that adjusts the container size based on the text content.

One workaround is to calculate the width of each line and if it falls below a specified maximum value, adjust the Text Box's width accordingly. It may also be necessary to add a slight buffer to ensure proper sizing.

var canvas = new fabric.Canvas("canvas");
var text = new fabric.Textbox("Add some text");

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

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

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

Take a look at this live example: https://codesandbox.io/s/stackoverflow-60411035-fabric-js-400-beta5-7s7id

It would be beneficial if a property like "max_width" existed for TextBox objects, allowing automatic adjustment of container size based on text length.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to activate jQuery validation when submitting a form instead of triggering it on blur

I am currently utilizing the Jquery Validation plugin to validate form fields upon submission. However, I have encountered an issue where incorrect email format triggers a validation message when moving to the next input field. This behavior is undesirable ...

The class functions perfectly under regular circumstances but ceases to operate once it is initialized

I'm currently developing a bluetooth remote in React Native. The issue I am facing is that my BLE class works perfectly on its own, but certain sections of code seem to malfunction when implemented within another class. import BLE from './Core/BL ...

Leveraging jQuery to delay the processing of AJAX requests

Managing a list of 15+ ajax requests that need to be executed in a specific sequence can be challenging. Each ajax call must wait for the previous one to finish before proceeding. This issue is compounded by the fact that the callback function for each aja ...

Generating a fresh object from an existing object by incorporating updated values using Angular and Ionic version 3

Currently, I am actively working on an Ionic 3 project that utilizes Angular framework. Within my project, I have a JSON object called 'person' which consists of data fields such as name, job, and home. One feature in my app is an Ionic toggle b ...

Attempting to have this .js lightbox appear as soon as the page loads

This Lightbox is absolutely stunning! However, I am looking for a way to automatically trigger the lightbox when the page loads. ...

Experience Markdown's Single Input Update Feature

I have recently developed a Markdown editor using Vue, similar to the examples found on Vue's website. However, my query is more related to implementation rather than Vue itself. Therefore, I am open to suggestions that do not necessarily involve Vue. ...

Jasmine raised an issue stating that Jodit is not recognized during the unit testing process

I'm currently testing a custom Jodit editor in my app, but even the automatic 'should create' test is failing with an error message of 'Jodit is not defined'. jodit.component.ts import { Component, OnInit, AfterViewInit, OnDestro ...

Tips for building dynamic web interfaces that allow for interactive communication in both directions

I'm struggling to find the right keywords to search for, so I'll explain what I'm attempting to accomplish using a basic example and see if anyone can suggest some potential techniques or technologies. Imagine a scenario where one or more i ...

Is there a way to change the color of just the most recently clicked anchor element <a>?

I have a sidebar with anchor elements (Link 1,2,3 in my HTML). I want the text color of these anchors to change when clicked. Additionally, I need only one anchor element to be colored at a time, meaning the previous one should return to its normal color. ...

Tips for updating an array in TypeScript with React:

Encountering an issue while updating my state on form submission in TypeScript. I am a newcomer to TS and struggling to resolve the error. enum ServiceTypeEnum { Replace = 'replace product', Fix = 'fix product', } interface IProduc ...

The jQuery autocomplete feature is malfunctioning, as it is unable to display any search

Creating a country list within an ajax call involves working with an array of objects: $.ajax({ url: '//maps.googleapis.com/maps/api/geocode/json?address=' + zipCode + '&region=AT', type: 'GET', dataType: &apo ...

What could be causing the entire app to malfunction when the Redux Provider tag is used

I am facing an issue while trying to integrate a React Toolkit app into my project. The error message I encountered is as follows: Error: Invalid hook call. Hooks can only be called inside the body of a function component. This error may occur due to one ...

Using HTML and jQuery to create a table with buttons to add or remove rows is a common practice. However, there

I have created a simple table with an "Add Row" button. Each new row has a "Remove" button. However, I am facing an issue in binding the 'click' event for the class 'remove'. Here is the code snippet: <script src="https://ajax.googl ...

Ways to fix a "define is not defined" issue when utilizing jasmine karma with compiled typescript for component testing

I'm faced with an issue in my typescript app where the compiled code is stored in a single file named myjs.js within the js folder. Additionally, I have karma jasmine configured on my workspace. Inside myjs.js, there's a segment of code like thi ...

A method to simultaneously retrieve all emitted values from multiple EventEmitters in Angular 7

I am facing a scenario where I have a parent component that consists of multiple child components. Each child component may differ from the others, creating a diverse structure within the parent component. Here's an example: ...

A guide on utilizing AngularJS to extract data from a webpage

I'm attempting to transfer the information from a specific page on my website and paste it into a file. I know how to post a sample text stored in a variable from Angular and save it in a file in the backend using Node Express, so writing a file isn&a ...

Refine the JSON data to only include the values you need

I've been spending a considerable amount of time on this challenge, but I'm facing difficulty in solving it. The issue at hand is that I have a JSON file that I am fetching from a URL, and my objective is to create a filter that displays only nam ...

Issue with GMap Compatibility on Specific Web Browsers

I'm currently facing an issue with implementing gMap [1] on a website. The map is functioning properly in Chrome and Safari, but it fails to display in Firefox, IE, and Opera (latest versions of all). I have ensured that the Google Map API key loads a ...

Grunt is designed to generate a single file, instead of producing multiple files

I have a simple Gruntfile that is designed to read a plain text file line by line and create an html file of the same name for each line. However, it seems to only work with one line in the file at a time, not multiple lines. Here is the console output wh ...

Throttle the RxJs interval based on the inner observables

Sorry if the way I am asking this question is not clear, I am having difficulty finding the right words to explain it. I am currently working on Selenium automation and here is how the process goes:- Go to a specific page Every 1 second, check if the pag ...