Create Professional-Looking Textboxes in Fabric.js with Strokes and Padding

Dinesh Rawat
calendar_month
May 21, 2024
timer
3 min
read time

Fabric.js is a powerful JavaScript library that provides a simple way to work with HTML5 canvas elements. It offers a range of features and tools to create interactive and visually appealing web applications. One of its key benefits is the ability to create custom classes, allowing developers to extend its functionality and tailor it to their specific needs.

In this blog, we will explore how to create and use a custom class in Fabric.js to create a stroked textbox with rounded corners and padding. We'll also discuss how to customize this class to fit different use cases. By the end of this blog, you'll have a better understanding of how to create custom classes in Fabric.js and how to leverage them to enhance your canvas applications.

Creating the Stroked Textbox Class

The Stroked Textbox class extends the default Textbox class in Fabric.js and adds several new features, including stroke width, stroke color, padding, and rounded corners. Let's take a look at each line of code in the class:

  • type: "textbox": This line specifies the type of object we are creating.
  • strokeWidth: 5: This line sets the width of the stroke to 5 pixels.
  • strokeColor: "#ffb64f": This line sets the color of the stroke to #ffb64f.
  • splitByGrapheme: true: This line specifies that the textbox should be split by graphemes.
  • rx: 0: This line sets the value of rx to 0, which determines the degree of rounding on the x-axis.
  • ry: 0: This line sets the value of ry to 0, which determines the degree of rounding on the y-axis.
  • toObject: This function returns an object that contains all the properties of the Textbox class, as well as the new properties added by the Stroked Textbox class.
  • _renderBackground: This function is responsible for rendering the background of the textbox with padding and rounded corners, as well as the stroke.

fabric.TextboxWithPadding = fabric.util.createClass(fabric.Textbox, {
      type: "textbox",
      strokeWidth: 5, // Define stroke width
      strokeColor: "#ffb64f", // Define stroke color
      splitByGrapheme: true,
    
      rx: 0, // Define rx value for rounded corners on x-axis
      ry: 0, // Define ry value for rounded corners on y-axis
      toObject: function () {
        return fabric.util.object.extend(this.callSuper("toObject"), {
          backgroundColor: this.get("backgroundColor"),
          padding: this.get("padding"),
          splitByGrapheme: this.get("splitByGrapheme"),
          rx: this.get("rx"),
          ry: this.get("ry")
        });
      },
    
      _renderBackground: function (ctx) {
        if (!this.backgroundColor) {
          return;
        }
        var dim = this._getNonTransformedDimensions();
        ctx.fillStyle = this.backgroundColor;
        ctx.fillRect(
          -dim.x / 2 - this.padding,
          -dim.y / 2 - this.padding,
          dim.x + this.padding * 2,
          dim.y + this.padding * 2
        );
        // Add stroke only at the top
        ctx.strokeStyle = this.strokeColor;
        ctx.lineWidth = this.strokeWidth;
        ctx.beginPath();
        ctx.moveTo(-dim.x / 2 - this.padding, -dim.y / 2 - this.padding);
        ctx.lineTo(-dim.x / 2 - this.padding, dim.y / 2 + this.padding);
        ctx.stroke();
    
        ctx.beginPath();
        ctx.strokeStyle = this.strokeColor;
        ctx.lineWidth = 0.2; // Set line width to 1
        ctx.lineTo(dim.x / 2 + this.padding, -dim.y / 2 - this.padding + 1);
        ctx.lineTo(dim.x / 2 + this.padding, dim.y / 2 + this.padding - 1);
        ctx.strokeStyle = "#9181fc";
    
        ctx.lineWidth = 0.2; // Set line width to 1
        ctx.lineTo(dim.x / 2 + this.padding - 1, dim.y / 2 + this.padding);
        ctx.lineTo(-dim.x / 2 - this.padding + 1, dim.y / 2 + this.padding);
        ctx.strokeStyle = "#9181fc";
    
        ctx.lineWidth = 0.2; // Set line width to 1
        ctx.lineTo(-dim.x / 2 - this.padding, dim.y / 2 + this.padding - 1);
        ctx.lineTo(-dim.x / 2 - this.padding, -dim.y / 2 - this.padding + 1);
        ctx.closePath();
    
        ctx.stroke();
    
        // if there is background color no other shadows
        // should be casted
        this._removeShadow(ctx);
      }
    });
    
    

Benefits of using the class

By using the Stroked Textbox class, we can create custom textboxes that have unique visual characteristics that are not available in the default Textbox class. This allows us to create more visually appealing and engaging canvas applications that stand out from the crowd.

Using the Stroked Textbox Class

To use the Stroked Textbox class, we simply need to create a new instance of the class and pass in the appropriate parameters. Here is an example of how to use the class to create a textbox with padding, rounded corners, and different stroke colors and widths:


const textbox = new fabric.TextboxWithPadding('Inpur field', {
    fontFamily: "Roboto",
    // fontSize: 20,
    padding: 5,
    width: 100,
    textAlign: 'left',
    //@ts-ignore
    // left: rect.left + 20,
    //@ts-ignore
    // top: rect.top + 10,  
    selectable: true,
    evented: true,
    editable: true,
    //@ts-ignore
    placeholder: "",
    splitByGrapheme: true,
    // lockScalingX: true,
    // lockScalingY: true,
    lockMovementX: true,
    lockMovementY: true,
    fill: '#000000',
    fontSize: 10,
    // stroke: OBJECT_BORDER_COLOR,
    strokeWidth: 1,
    backgroundColor: "#d5d1eb",
    //@ts-ignore
    left: 30,
    //@ts-ignore
    top: 30,
    className: "text_box_with_padding",
    includeDefaultValues: true,
    intersectsWithFrame: true,
    hasControls: false,
    hasBorders: true,
});

In this example, we have set the fontFamily, padding, width, textAlign, selectable, evented, editable, splitByGrapheme, fill, fontSize, strokeWidth, backgroundColor, hasControls, and hasBorders properties to customize the appearance and behavior of the textbox.

Customizing the Stroked Textbox Class

To customize the Stroked Textbox class further, we can modify the values of the parameters used in the class, or we can create a new subclass that extends the Stroked Textbox class and adds new functionality. Here are some tips on how to customize the class to fit specific needs:

  1. Adjust the stroke width: To change the width of the stroke, modify the value of strokeWidth. A higher value will create a thicker stroke, while a lower value will create a thinner stroke. For example, setting strokeWidth to 10 will create a textbox with a thicker stroke than the default value of 5.
  2. Change the stroke color: To adjust the color of the stroke, modify the value of strokeColor. You can set the value to a hex code or a named color. For example, setting strokeColor to "#ff0000" will create a red stroke.
  3. Modify the padding: To adjust the amount of padding around the textbox, modify the value of padding. This parameter determines the amount of space between the text and the edge of the textbox. For example, setting padding to 10 will increase the amount of space around the text.
  4. Adjust the rounding of the corners: To change the degree of rounding on the corners of the textbox, modify the values of rx and ry. These parameters determine the amount of rounding on the x and y axes, respectively. For example, setting rx and ry to 10 will create a textbox with more rounded corners.

Additionally, you can create a new subclass that extends the Stroked Textbox class and adds new functionality. This allows you to customize the class even further and add new features to the textbox. For example, you could create a subclass that adds a drop shadow to the textbox or one that changes the font based on the user's input. The possibilities are endless, and the Stroked Textbox class provides a great foundation to build upon.